当显式转换有效时,为什么此Scala隐式转换失败?

时间:2011-12-12 09:20:55

标签: scala

为什么即使明确调用该函数,以下隐式转换也不起作用?

scala> implicit def view[A, C](xs: C)(implicit ev: C <:< Iterable[A]) = new { def bar = 0 } 
view: [A, C](xs: C)(implicit ev: <:<[C,scala.collection.immutable.Iterable[A]])java.lang.Object{def bar: Int}

scala> List(1) bar
<console>:147: error: Cannot prove that List[Int] <:< scala.collection.immutable.Iterable[A].
              List(1) bar
                  ^

scala> view(List(1)) bar
res37: Int = 0

2 个答案:

答案 0 :(得分:0)

我并没有真正回答你的问题(例如,我正在回答&#34;我如何做这项工作&#34;但不是&#34;为什么它不起作用&#34; 34);无论如何,希望这将有助于其他人在回答方面取得一些进展。

所以......在第一种情况下,假设C是List [Int],编译器无法正确推断出A是Int。老实说,我更加惊讶的是,明确地传递List实际上是有效的,因为A和C之间的关系是间接的(你有A和C,因为C是Iterable [A]的子类型,因为C是a列出[Int],然后A必须是一个Int;不是一个非常简单的推理......)。

你可以通过更清楚地了解C和A之间的关系来使其发挥作用,如下所示:

scala> implicit def view[A, C[A]](xs: C[A])(implicit ev: C[A] <:< Iterable[A]) = 
       new { def bar = 0 }
view: [A, C[A]](xs: C[A])(implicit ev: <:<[C[A],Iterable[A]])java.lang.Object{def bar: Int}

scala> List(1) bar
res0: Int = 0

或(鉴于您未使用A):

scala> implicit def view[C](xs: C)(implicit ev: C <:< Iterable[_]) = 
       new { def bar = 0 }

scala> List(1) bar
res1: Int = 0

答案 1 :(得分:0)

简单地说,正如错误消息所示,它无法推断A。编译器没有信息可以用来推断A必须是什么,所以必须假设它可以是任何东西。

您可以反驳它可以从A推断出C <:< Iterable[A],但这样可以解决问题:不使用<:<检查约束,而是使用约束来推断出A的类型!那个逻辑不合理。