Scala 为什么可以';当类型是协变的时,我们是否提供隐式类型类?

Scala 为什么可以';当类型是协变的时,我们是否提供隐式类型类?,scala,functional-programming,typeclass,scalaz,scala-cats,Scala,Functional Programming,Typeclass,Scalaz,Scala Cats,我在设计代数数据类型时遇到了一个无法提供隐式类型类的问题。以下是我所拥有的: sealed abstract class Stream[+F[_], +T] { def run()(implicit M: Monad[F]): F[Unit] = Stream.run(this) } object Stream{ final case object Halt extends Stream[Nothing, Nothing] private def run[F[_], T](stre

我在设计代数数据类型时遇到了一个无法提供隐式类型类的问题。以下是我所拥有的:

sealed abstract class Stream[+F[_], +T] {
  def run()(implicit M: Monad[F]): F[Unit] = Stream.run(this)
}

object Stream{
  final case object Halt extends Stream[Nothing, Nothing]
  private def run[F[_], T](stream: Stream[F, T])(implicit M: Monad[F]): F[Unit] = stream match {
    case Halt => M.pure()
  }
}
我得到了编译错误

Error:(10, 22) covariant type F occurs in invariant position in type 
     Monad[F] of value M def run()(implicit M: Monad[F]): F[Unit] = M.pure()

我使其协变,以便能够在不强制转换的情况下返回
Halt extends Stream[Nothing,Nothing]
,但我需要
Monad[F]
typeclass,以便将其操作用于提供的上下文
F[\u]
。在这种情况下,解决方案是什么?

只有当
Monad
是反向变量时,才会编译。否则,您必须:

val stream: Stream[Nothing, Nothing] = Halt
val stream1: Stream[Maybe, Int] = stream // by covariance
val x = stream1.run()(implicitly[Monad[Maybe]])
但是
Halt.run
只接受
Monad[Nothing]
,因此
Monad[Maybe]
必须是
Monad[Nothing]
的子类型

在这种情况下,解决方案是什么

不这样定义
运行
?一般来说,因为scalaz和cats决定使它们的类型类保持不变,所以在尝试将它们用于协变/逆变类型时会遇到麻烦