【发布时间】:2012-11-10 23:56:10
【问题描述】:
假设我们有以下两个特征:
trait Foo[A] { def howMany(xs: List[A]) = xs.size }
trait Bar
还有从第二个到第一个的隐式转换:
implicit def bar2foo[A](bar: Bar) = new Foo[A] {}
我们创建一个Bar 和一个整数列表:
val bar = new Bar {}
val stuff = List(1, 2, 3)
现在我希望以下工作:
bar howMany stuff
但它没有:
scala> bar howMany stuff
<console>:13: error: type mismatch;
found : List[Int]
required: List[A]
bar howMany stuff
^
所以我们去the spec,它有这样的说法(粗体强调是我的):
视图应用于三种情况。
[此处不相关。]
在选择 em 中,e 类型为 T,如果选择器 m 不表示 T 的成员。在这种情况下,搜索一个视图 v 适用于 e 并且其结果包含名为 m 的成员。这 搜索与隐式参数的情况一样进行,其中 隐式作用域是 T 之一。如果找到这样的视图, 选择 e.m 被转换为 v(e).m。
在选择 em(args) 中,e 类型为 T,如果选择器 m 表示 T 的一些成员,但这些成员都不适用于参数 args。在这种情况下,搜索视图 v 适用于 e 并且其结果包含方法 m 这适用于 args。搜索继续进行 隐式参数,其中隐式范围是 T 之一。如果 找到这样的视图,选择 e.m 转换为 v(e).m(args).
所以我们尝试了以下方法,认为它一定太荒谬了:
trait Foo[A] { def howMany(xs: List[A]) = xs.size }
trait Bar { def howMany = throw new Exception("I don't do anything!") }
implicit def bar2foo[A](bar: Bar) = new Foo[A] {}
val bar = new Bar {}
val stuff = List(1, 2, 3)
但确实如此(至少在 2.9.2 和 2.10.0-RC2 上):
scala> bar howMany stuff
res0: Int = 3
这会导致一些非常奇怪的行为,例如this workaround 中的this problem。
我有三个(密切相关的)问题:
- 是否有一种直接的方法(即不涉及添加具有适当名称的假方法)在上述原始案例中正确应用视图?
- 有人可以提供解释这种行为的规范吗?
- 假设这是预期的行为,这是否有意义?
我也非常感谢您之前讨论过这个问题的任何链接——我对 Google 的运气并不好。
【问题讨论】: