2012-12-03 3 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" 

(I는 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 ... 

저의 이해는 컴파일러의 trie (bar 정의로 가져온) 범위에 MonadPlus[M] 인스턴스가있을 수 있다는 것을 고려하지 않고 foo 호출에 적합한 MonadPlus[M] 인스턴스 (listInstance 및 optionInstance)를 이미 찾습니다. . 이 단계에서는 모호성을 선언합니다.

그런 다음 bar2bar3에 명시 적으로 사용할 수있는 인스턴스를 지정하고 bar4 당신은 유형 매개 변수를 제공 M 이러한 제약 범위에서 유일하게 암시가 implicitly[MonadPlus[M]] 때문에 foo 통화 모호하지 Int.

+0

죄송합니다. 1 년 후 대답은 나에게 명백한 것처럼 보인다. 'bar1'은 어떤 종류의'MonadPlus'가'foo'에 전달 될지를 지정하지 않습니다; 'bar2','bar3','bar4'는 명시 적 인수 또는 형식 인수를 통해 수행됩니다. 솔직히 내가 뭘 생각하는지 모르겠다. – arya