5

以下是我真正问题的简化版本:

class Z[T]
object E extends Enumeration {
  implicit val z = new Z[Value] 
  val X, Y = Value
}
implicit def f[T : Z] = (getter: T) => 0
implicit def o[T](v: Option[T])(implicit toInt: T => Int) = 0
def e: Option[E.Value] = null
val b: Int = e

这有效,b 隐式转换为 o(e)(f(Ez))。但有以下小的变化:

implicit def f[T : Z] = (setter: T => Unit) => 0
implicit def o[T](v: Option[T])(implicit toInt: (T => Unit) => Int) = 0

尽管与原始代码没有本质区别,但它未能找到适当的隐式值 Ez,而手动显式转换为 o(e)(f(Ez)) 仍然有效。

我知道隐式参数的实现还没有完成,还有很多未解决的问题。如果这是其中之一,我想向 Scala 贡献者报告。所以我的问题是,a) 这真的是一个错误吗?b) 如果是这样,我可以在哪里以及如何提交错误以便将来修复?

更新

特拉维斯的回答就像一个魅力!顺便说一句,上面的代码是我原来问题的解决方法:

implicit object E extends Enumeration { val X, Y = Value }
implicit object F extends Enumeration { val X, Y = Value }
implicit def f[T <: Enumeration](getter: T#Value)(implicit e: T) = 0
implicit def o[T](v: Option[T])(implicit toInt: T => Int) = 0
val b: Int = Some[E.Value](null)

在这段代码中,情况正好相反:它适用于 setter 版本,但不适用于更简单的 getter 版本。编译器抱怨是否使用 E 或 F 作为隐式参数令人困惑,尽管使用 F 实际上并没有编译也没有意义。我通过做类似的事情设法让它工作:

implicit def f[S <% T => T, T <: Enumeration](getter: T#Value)(implicit e: T) = 0

这行得通,虽然我能以某种方式让它工作,但我仍然不明白这个魔法背后的逻辑。

4

1 回答 1

6

您遇到了Scala 类型推断系统的这种限制的另一种变体。

编译器将在第一种情况下解析Tfor fif,它正在寻找从普通 oldE.Value到的隐式转换Int,但不是在第二种情况下,它想要从E.Value => Unit(ie, Function1[E.Value, Unit]) 到的转换Int

幸运的是,在这种情况下有一个简单的解决方法——只需使用视图绑定:

implicit def f[F <% T => Unit, T: Z] = (setter: F) => 0

这将脱糖为以下内容:

implicit def f[F, T](implicit st: F <:< (T => Unit), ev: Z[T]) = (setter: F) => 0

现在,当编译器想要从E.Value => Unitto转换时,Int它可以立即解析FE.Value => Unit,然后再 解析TE.Value.

于 2013-06-24T20:49:10.473 回答