有争议的守则
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))由于某种原因,在中,我在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源中没有方差注释,那么这里的处理方式是什么呢?为什么需要方差注释?是否真的有需要,还是有办法绕过它?
发布于 2014-06-05 02:50:08
我认为,在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)))"请注意,无论用哪种方式将元素应用于函数式映射,都会得到相同的结果(您是version和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]类型的函数。所以编译器可能会看到挂起接受一个Free,所以它使这个(A => Free[F, A]) => F[Free[F, A]]很高兴地以Return[F, A].apply作为参数。当您以另一种方式应用参数时,您将被强类型为Return,而不是推断函数Free。
https://stackoverflow.com/questions/24049030
复制相似问题