gpt4 book ai didi

scala - 如何在 scalaz 中堆叠 ReaderT 和 WriterT 转换器?

转载 作者:行者123 更新时间:2023-12-04 15:59:47 25 4
gpt4 key购买 nike

我在 scalaz 中使用 monad 转换器.我正在尝试将 Reader 顶部的 Writer 与底层 Id 堆叠在一起。单子(monad)。为了组合它们,我使用 MonadReaderMonadWriter类型类。

我设法编译并运行了以下代码示例 没有 作者(即 Reader monad,即 ReaderT[Id.Id, String, A] )。添加 WriterT 时到堆栈,我得到编译错误:

Gist.scala:10: could not find implicit value for parameter F: scalaz.MonadReader[Gist.R,String]
val MR = MonadReader[R, String]
^

如何获得 MonadReader 的实例为我的变压器堆栈?我必须使用 ReaderWriterStateT吗?还是有其他方法?

完整代码:
import scalaz.{Id, MonadListen, MonadReader, ReaderT, WriterT}

object Gist {
import scalaz.std.list._
import scalaz.syntax.monad._

type P[A] = ReaderT[Id.Id, String, A]
type R[A] = WriterT[P, List[String], A]

val MR = MonadReader[R, String]
val MW = MonadListen[R, List[String]]

def apply: R[String] = MR.ask >>= { greeting =>
MW.tell(List(s"greeting $greeting")) >>= { _ =>
MW.point(s"Hello $greeting")
}
}
}

最佳答案

我不完全确定为什么 Scalaz 不提供此实例(或类似 monad 转换器的 MonadReader 实例),但我猜答案与 WriterTInstanceN 的事实有关。已经goes past 11并添加 MonadReader只会让事情变得更加困惑。

您可以在 Scalaz 的 GitHub 问题中四处寻找(或者甚至在 IRC channel 上询问您是否愿意接受这类事情),但我不确定答案是否那么重要。

您可以直接从 Haskell 的 mtl 移植实例。 :

instance (Monoid w, MonadReader r m) => MonadReader r (Strict.WriterT w m) where
ask = lift ask
local = Strict.mapWriterT . local
reader = lift . reader

翻译成 Scala 的代码如下所示:
import scalaz.{ MonadReader, MonadTrans, Monoid, WriterT }
import scalaz.syntax.monad._

implicit def monadReaderForWriterT[F[_], I, W](implicit
F: MonadReader[F, I],
W: Monoid[W]
): MonadReader[WriterT[F, W, ?], I] = new MonadReader[WriterT[F, W, ?], I] {
def ask: WriterT[F, W, I] = MonadTrans[WriterT[?[_], W, ?]].liftM(F.ask)

def local[A](f: I => I)(fa: WriterT[F, W, A]): WriterT[F, W, A] =
fa.mapT(F.local(f))

def point[A](a: => A): WriterT[F, W, A] = a.point[WriterT[F, W, ?]]
def bind[A, B](fa: WriterT[F, W, A])(
f: A => WriterT[F, W, B]
): WriterT[F, W, B] = fa.flatMap(f)
}

请注意,我使用的是 kind-projector ,因为类型 lambda 版本将更像是 Haskell 版本的四到五倍,而不是仅仅三倍。

定义此实例后,您可以编写以下内容:
import scalaz.{ Id, MonadListen, ReaderT }
import scalaz.std.list._

type P[A] = ReaderT[Id.Id, String, A]
type R[A] = WriterT[P, List[String], A]

val MR = MonadReader[R, String]
val MW = MonadListen[R, List[String]]

def apply: R[String] = MR.ask >>= { greeting =>
MW.tell(List(s"greeting $greeting")) >>= { _ =>
MW.point(s"Hello $greeting")
}
}

关于scala - 如何在 scalaz 中堆叠 ReaderT 和 WriterT 转换器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43337261/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com