Pat*_*ont 51 scala type-inference return-type implicit scalaz
给定一个类型类,其中应根据返回类型执行实例选择:
case class Monoid[A](m0: A) // We only care about the zero here
implicit def s[T] : Monoid[Set[T]] = Monoid(Set.empty[T])
implicit def l[T] : Monoid[List[T]] = Monoid(List.empty[T])
def mzero[A](implicit m: Monoid[A]) : A = m.m0
Run Code Online (Sandbox Code Playgroud)
为什么Scala(2.11.6)无法解析正确的实例:
scala> mzero : List[Int]
<console>:24: error: ambiguous implicit values:
both method s of type [T]=> Monoid[Set[T]]
and method l of type [T]=> Monoid[List[T]]
match expected type Monoid[A]
mzero : List[Int]
^
Run Code Online (Sandbox Code Playgroud)
当它有没有问题,使用时发现基于返回类型的隐式隐函数(我们在这里重新定义它为我来说明它是多么相似mzero)
def i[A](implicit a : A) : A = a
scala> i : Monoid[List[Int]]
res18: Monoid[List[Int]] = Monoid(List())
Run Code Online (Sandbox Code Playgroud)
而Monoid[A]不是Monoid[List[Int]]在错误消息中令人费解.
我会假设许多scalaz贡献者熟悉这个问题,因为它似乎限制了scala中类型类的便利性.
编辑:我正在考虑让这个工作没有放弃类型推断.否则我想明白为什么那是不可能的.如果将此限制记录为Scala问题,我找不到它.
1)重写代码后如下:
case class Monoid[A](m0: A) // We only care about the zero here
implicit def s[T] : Monoid[Set[T]] = Monoid(Set.empty[T])
implicit def l[T] : Monoid[List[T]] = Monoid(List.empty[T])
def mzero[A]()(implicit m: Monoid[A]) : A = m.m0
val zero = mzero[List[Int]]()
val zero2: List[Int] = mzero()
Run Code Online (Sandbox Code Playgroud)
然后就清楚为什么会这样了。
2)在您必须设置 mzero 之后,def mzero[A]()(implicit m: Monoid[_ <: A]) : A = m.m0您启用了附加类型推断来解析存在类型。编译器从所需的返回类型中获取实际类型。如果你愿意的话你可以检查一下def mzero[A <: B, B]()(implicit m: Monoid[A]) : A = m.m0。
3)当然,所有这些行为只是编译器的微妙之处,我认为这种部分情况并不需要深入理解。
| 归档时间: |
|
| 查看次数: |
693 次 |
| 最近记录: |