【问题标题】:type parameter inference + higher order types + type classes = :-(类型参数推断 + 高阶类型 + 类型类 = :-(
【发布时间】:2012-11-21 09:37:09
【问题描述】:
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 中得到相同的结果)

【问题讨论】:

    标签: scala implicit scalaz typeclass


    【解决方案1】:

    如果你简单地写,你会得到同样的错误信息:

    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适用于foo 调用的特定MonadPlus[M] 实例(listInstance 和optionInstance)。在这个阶段,它只是声明了一个歧义。

    然后在bar2bar3 中明确指定要使用的实例,在bar4 中给出MInt 的类型参数,这在foo 调用中是没有歧义的,因为只有在这些约束的范围内隐含的是implicitly[MonadPlus[M]]

    【讨论】:

    • 哎呀,是的。一年后,答案对我来说似乎很明显。 bar1 没有指定将什么样的MonadPlus 传递给foobar2,bar3,bar4 可以通过显式参数或类型参数来实现。老实说,我不知道我在想什么。
    猜你喜欢
    • 2020-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多