2012-12-03 69 views
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? 

build.sbt:类型参数推断+高阶类型+型类= :-(

scalaVersion := "2.9.2" 

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

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

回答

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 ... 

我的理解是,编译器线索s来检查bar1方法的“主体”,并且没有考虑范围内可能存在MonadPlus[M]实例(由bar定义带来),它已经找到2个特定的MonadPlus[M]实例(listInstance和optionInstance),它们适用于foo调用。在这个阶段,它只是宣布了一个模棱两可的问题。

然后在bar2bar3您明确指定要使用的实例,并在bar4你给的类型参数,这些参数MInt这是不是在foo呼叫模糊,因为在范围内唯一的隐性这些限制是implicitly[MonadPlus[M]]

+0

哎呀,是的。一年后,答案似乎对我很明显。 'bar1'不指定传递给'foo'的是哪种'MonadPlus'; 'bar2','bar3','bar4',通过显式参数或类型参数。老实说,我不知道我在想什么。 – arya