4
import scalaz._; import Scalaz._

def foo[M[_]:MonadPlus,A](a:A) = a.point[M]
// foo: [M[_], A](a: A)(implicit evidence$1: scalaz.MonadPlus[M])M[A]

def bar1[M[_]:MonadPlus](i:Int): M[Int] = 
  foo(i) // <-- error: ambiguous implicit values

// this works, but why?  Isn't it just the same?
def bar2[M[_]:MonadPlus](i:Int): M[Int] = 
  foo(i)(implicitly[MonadPlus[M]])

def bar3[M[_]](i:Int)(implicit m:MonadPlus[M]): M[Int] = 
  foo(i)(m) // slightly less surprising that this works

def bar4[M[_]:MonadPlus](i:Int): M[Int] = 
  foo[M,Int](i) // this also works, but why?

构建.sbt:

scalaVersion := "2.9.2"

libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.0.0-M5"

(虽然我在 2.10.0-RC3 中得到了相同的结果)

4

1 回答 1

2

如果您简单地编写,您会收到相同的错误消息:

import scalaz._; import Scalaz._

def foo[M[_]:MonadPlus,A](a:A) = a.point[M]

foo(1) // <-- error: ambiguous implicit values
       // both value listInstance ...
       // and value optionInstance ...

我的理解是编译器尝试对bar1方法的“主体”进行类型检查,并且没有考虑范围内可能存在一个MonadPlus[M]实例(由bar定义带来),它已经找到了 2 个MonadPlus[M]适合的特定实例(listInstance 和 optionInstance)foo调用。在这个阶段,它只是声明了一个歧义。

然后 inbar2bar3明确指定要使用的实例,并在 in 中bar4给出类型参数,这些参数在调用中是MInt不模棱两可的,foo因为这些约束的唯一隐含范围是implicitly[MonadPlus[M]].

于 2012-12-04T00:05:16.847 回答