我一直在和Scalaz一起玩,以获得scala的一点点haskell感觉 . 为了理解scala中的工作原理,我开始自己实现各种代数结构,并且遇到了Scalaz人员提到过的行为 .
这是我实现仿函数的示例代码:
trait Functor[M[_]] {
def fmap[A, B](a: M[A], b: A => B): M[B]
}
sealed abstract class Foo[+A]
case class Bar[A]() extends Foo[A]
case class Baz[A]() extends Foo[A]
object Functor {
implicit val optionFunctor: Functor[Option] = new Functor[Option]{
def fmap[A, B](a: Option[A], b: A => B): Option[B] = a match {
case Some(x) => Some(b(x))
case None => None
}
}
implicit val fooFunctor: Functor[Foo] = new Functor[Foo] {
def fmap[A, B](a: Foo[A], b: A => B): Foo[B] = a match {
case Bar() => Bar()
case Baz() => Baz()
}
}
}
object Main {
import Functor._
def some[A](a: A): Option[A] = Some(a)
def none[A]: Option[A] = None
def fmap[M[_], A, B](a: M[A])(b: A => B)(implicit f: Functor[M]): M[B] =
f.fmap(a, b)
def main(args: Array[String]): Unit = {
println(fmap (some(1))(_ + 1))
println(fmap (none)((_: Int) + 1))
println(fmap (Bar(): Foo[Int])((_: Int) + 1))
}
}
我为Option写了一个仿函数实例,伪造了一个类型Foo . 问题是如果没有显式类型注释或包装器方法,scala无法推断隐式参数
def some[A](a: A): Option[A] = Some(a)
println(fmap (Bar(): Foo[Int])((_: Int) + 1))
Scala推断类型如Functor [Bar]和Functor [Some]没有那些变通方法 .
这是为什么?有谁能请指出我在语言规范中定义这种行为的部分?
问候,raichoo
1 回答
您要求编译器执行两个任务:
fmap
类型参数的本地类型推断(第6.26.4节),以及隐式参数(第7.2节)f
的隐式搜索 . 参考文献是Scala Reference .事情按此顺序排列:
对
Functor[Some]
的隐式搜索失败;Functor[Option]
不符合 .