简体   繁体   English

高等类型参数的(co | in)方差

[英](co | in)variance of Higher Kinded type parameter

the code in question 有问题的代码

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))

Now for some reason in the eclipse scala ide I'm getting a error with liftF this error 现在由于某种原因在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)

Now in the scalaz source there's no variance annotation, so what's the deal here? 现在,在scalaz源码中没有方差注释,那么这里要做什么? why the need for the variance annotation? 为什么需要方差注释? is there are really need or is there a way around it? 是否真的有需要或有解决的办法?

I think you just have the functor arguments backwards on F.map . 我认为您只是在F.map向后倒有函子参数。 Give this a try: 试试看:

  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)))"

Note that either way you apply the elements to functor map you'll get the same result (you're version and the scalaz 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]
})

In this case reverse and normal are both F[Return[F, A]] . 在这种情况下, reversenormal均为F[Return[F, A]] The way you apply the parameters is only helpful in the context of Suspend : 您应用参数的方式仅在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

I'm sure if you dig through the scala language spec long enough you can find out why the type inference works this way. 我敢肯定,如果您对Scala语言规范进行了足够长时间的挖掘,就可以找出为什么类型推断如此有效的原因。 If I had to guess, when fa is applied to F.map you get a function that's of type (A => B) => F[B] . 如果我不得不猜测,当fa应用于F.map您会得到(A => B) => F[B]类型的函数。 So the compiler probably looks and sees that Suspend takes a Free so it makes this (A => Free[F, A]) => F[Free[F, A]] which will gladly take Return[F, A].apply as an argument. 因此,编译器可能会看到并看到Suspend接受了Free因此使它成为(A => Free[F, A]) => F[Free[F, A]] ,这将很高兴地使用Return[F, A].apply作为争论。 When you apply the arguments the other way you're strongly typed to Return instead of inferring a function Free . 当您以其他方式应用参数时,强烈建议您键入Return而不是推断Free函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM