Monad Transformer在Scala中堆叠
发布时间:2020-12-16 18:20:34 所属栏目:安全 来源:网络整理
导读:我正在学习 Scala中的monad变换器,但是遇到了一个我发现到目前为止无法解决的问题.在我的monad变换器堆栈中,我组成了Either和State monad.但是,我无法调用属于两个monad之一的函数: import scalaz._import Scalaz._object Minimal { type Inner[A] = Either
我正在学习
Scala中的monad变换器,但是遇到了一个我发现到目前为止无法解决的问题.在我的monad变换器堆栈中,我组成了Either和State monad.但是,我无法调用属于两个monad之一的函数:
import scalaz._ import Scalaz._ object Minimal { type Inner[A] = EitherT[Id,String,A] type Outer[F[+_],A] = StateT[F,Int,A] type Stack[A] = Outer[Inner,A] def foo:Stack[Int] = for { n <- get[Int] } yield { 2 * n } def main(args: Array[String]): Unit = { val x = foo.eval(8) println(x) } } 失败,出现以下错误消息: [error] Minimal.scala:10: type mismatch; [error] found : scalaz.IndexedStateT[scalaz.Id.Id,Int] [error] required: Minimal.Stack[Int] [error] (which expands to) scalaz.IndexedStateT[Minimal.Inner,Int] [error] n <- get[Int] 如果我将monad变换器堆栈更改为: type Stack[A] = State[Int,A] 该程序编译和运行没有问题.有谁知道我在这里做错了什么? 解决方法
方法调用get [Int]返回一个IndexedStateT [Id,Int].您的Stack [Int]扩展为IndexedStateT [Inner,Int],其中Inner是EitherT [Id,A].这有点难以理解,所以我会简化你的例子.
我们使用Option创建一个StateT,而不是Inner类型别名. type Stack[A] = StateT[Option,A] get [Int]的赋值仍然会失败. val x:Stack[Int] = get[Int] //type mismatch; // found : scalaz.State[Int,Int] // (which expands to) scalaz.IndexedStateT[scalaz.Id.Id,Int] // required: Minimal.Stack[Int] // (which expands to) scalaz.IndexedStateT[Option,Int] 为了解决这个问题,我们需要将变压器提升到一个选项: val x:Stack[Int] = get[Int].lift[Option] 如果您将其转换为示例代码,则需要将State提升为内部.请注意,您还需要将Inner的定义更改为协变: type Inner[+A] = EitherT[Id,A] type Stack[A] = StateT[Inner,A] val x:Stack[Int] = get[Int].lift[Inner] 为了能够在不手动提升的情况下编写此内容,您可以引入隐式转换.完整的例子: type Inner[+A] = EitherT[Id,A] type Outer[F[+_],A] type Stack[A] = Outer[Inner,A] implicit def liftToStack[A](x:Outer[Id,A]):Stack[A] = x.lift[Inner] def foo: Stack[Int] = for { n <- get[Int] } yield { 2 * n } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |