我正在设计我的代数数据类型,并面临无法提供隐式类型类的问题。这就是我所拥有的:
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]
类型类,以便将其操作用于提供的上下文F[_]
。在这种情况下会有什么解决方案?
答案 0 :(得分:3)
只有当Monad
contra -variant时才会编译。否则你有:
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]
的子类型。
在这种情况下会有什么解决方案?
不要像这样定义run
?一般来说,因为scalaz和猫决定使他们的类型不变,所以当你尝试在co / contravariant类型中使用它们时会遇到麻烦。