【发布时间】:2019-03-27 14:50:09
【问题描述】:
我在SO上多次看到这个问题,但无论我怎么努力,我都无法编译下面的代码。目标是实现Functor 实现更简单的Reader(代码为here):
trait Functor[F[_]] {
def fmap[A, B](fa: F[A])(f: A => B): F[B]
}
implicit class FunctorOps[F[_]: Functor, A](self: F[A]) {
def fmap[B](f: A => B): F[B] = implicitly[Functor[F]].fmap(self)(f)
}
case class Reader[A, B](run: A => B)
type ReaderF[X] = ({ type L[A] = Reader[X, A] })
implicit def readerFunctors[E]: Functor[ReaderF[E]#L] =
new Functor[ReaderF[E]#L] {
override def fmap[A, B](fa: Reader[E, A])(f: A => B): Reader[E, B] =
Reader(e => f(fa.run(e)))
}
val foo = Reader[String, Int](_ => 42)
foo.fmap(_ + 1) // does not compile
我尝试通过以下方式绕过隐式机制:
FunctorOps(foo).fmap(_ + 1)
但这会输出以下编译错误:
Error:(82, 23) type mismatch;
found : com.fp.Scratchpad.Reader[String,Int]
required: ?F[?A]
Note that implicit conversions are not applicable because they are ambiguous:
both method ArrowAssoc in object Predef of type [A](self: A)ArrowAssoc[A]
and method Ensuring in object Predef of type [A](self: A)Ensuring[A]
are possible conversion functions from com.fp.Scratchpad.Reader[String,Int] to ?F[?A]
FunctorOps(foo).fmap(_ + 1)
提前感谢您的帮助。
更新
为了确保我的 FunctorOps 是正确的,我为 Id 创建了一个仿函数实例:
case class Id[A](value: A)
implicit val idF: Functor[Id] = new Functor[Id] {
override def fmap[A, B](fa: Id[A])(f: A => B): Id[B] = Id(f(fa.value))
}
val id = Id(42)
id.fmap(_ + 1) // compiles
所以问题不是来自FunctorOps 隐式类。我怀疑 Scala 在使用 lambda 类型时会遇到困难......
更新 2
我试图简化问题但没有成功:
trait Functor[F[_]] {
def map[A, B](x: F[A])(f: A => B): F[B]
}
implicit class Ops[F[_], A](fa: F[A])(implicit F: Functor[F]) {
def map[B](f: A => B): F[B] = F.map(fa)(f)
}
type FF[A] = ({ type F[B] = A => B })
implicit def ff[E]: Functor[FF[E]#F] = new Functor[FF[E]#F] {
override def map[A, B](x: E => A)(f: A => B): E => B = e => f(x(e))
}
val f: String => Int = _ => 42
val value: Functor[FF[String]#F] = ff[String]
val ops = new Ops[FF[String]#F, Int](f)(value)
// These compile
ops.map(_ + 1)("")
value.map(f)(_ + 1)("")
// This not
f.map(_ + 1)
【问题讨论】:
-
你的 Scala 版本是多少?第一个编译在scastie.scala-lang.org/gpRKdKjNS4KLTAq7Zwptsw。实际上我很惊讶它似乎也可以在旧版本中使用,我认为您需要 2.12 或 2.11.11+。
-
我刚刚检查过,Scala 版本是 2.12.8。尝试用 IDEA 和 sbt 编译 :(
-
你是在工作表中运行这个吗?
-
不,我也尝试编译这个原始 sbt
标签: scala intellij-idea functional-programming