有问题的代码
trait Functor[F[_]] {
def map[A, B](f: A => B): F[A] => F[B]
}
sealed abstract class Free[F[_], A]
case class Return[F[_], A](x: A) extends Free[F, A]
case class Suspend[F[_], A](x: F[Free[F, A]]) extends Free[F, A]
case class Bind[F[_], A, B](x: () => Free[F, A], f: A => Free[F, B]) extends Free[F, B]
// this is the problem child
def liftF[F[_], A](x: => F[A])(implicit F: Functor[F]) =
Suspend[F, A](F.map { Return[F, A] }(x))
现在由于某种原因,在eclipse scala ide中我遇到了一个与liftF有关的错误 这个错误
- type mismatch; found : F[core01.Free.Return[F,A]] required: F[core01.Free[F,A]] Note: core01.Free.Return[F,A] <: core01.Free[F,A], but type
F is invariant in type _. You may wish to define _ as +_ instead. (SLS 4.5)
现在在scalaz源代码中没有方差注释,那么这里的交易是什么?为什么需要方差注释?是真的需要还是有办法绕过它?
答案 0 :(得分:1)
我认为你只是在F.map
上反向提出了仿函数参数。试一试:
def liftF[F[_], A](x: => F[A])(implicit F: Functor[F]) =
Suspend[F, A](F.map(x) { Return[F, A] } )
println(liftF(List(1, 2)))
"Suspend(List(Return(1), Return(2)))"
请注意,无论采用哪种方式将元素应用于仿函数映射,您都会得到相同的结果(您是版本和scalaz版本):
def mapReverse[F[_], A, B](implicit F: Functor[F]) = {
(f:A => B) => (fa:F[A]) => F.map(fa)(f)
}
val reverse = mapReverse(F)({
Return[F, A]
})(x)
val normal = F.map(x)({
Return[F, A]
})
在这种情况下,reverse
和normal
都是F[Return[F, A]]
。应用参数的方式仅在Suspend
:
Suspend[F, A](F.map(x)({ Return[F, A] })) // works great
Suspend[F, A](normal) // fails to compile
Suspend[F, A](reverse) // fails to compile
我敢肯定,如果你仔细研究scala语言规范,你就可以找到为什么类型推断以这种方式工作。如果我不得不猜测,当fa
应用于F.map
时,您会得到类型为(A => B) => F[B]
的函数。因此,编译器可能会查看并看到Suspend接受Free
,因此它会使(A => Free[F, A]) => F[Free[F, A]]
很快将Return[F, A].apply
作为参数。当您以强制键入Return
的方式应用参数时,而不是推断函数Free
。