如何在scalaz中堆叠ReaderT和WriterT变换器?
发布时间:2020-12-16 18:09:32 所属栏目:安全 来源:网络整理
导读:我在 scalaz玩monad变形金刚.我正在尝试将读取器顶部的Writer与底层Id monad堆叠在一起.为了组合它们,我使用的是MonadReader和MonadWriter类型. 我设法编译并运行以下代码示例而没有编写器(即使用Reader monad,即ReaderT [Id.Id,String,A]).将WriterT添加到
我在
scalaz玩monad变形金刚.我正在尝试将读取器顶部的Writer与底层Id monad堆叠在一起.为了组合它们,我使用的是MonadReader和MonadWriter类型.
我设法编译并运行以下代码示例而没有编写器(即使用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,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频道询问您是否有这种事情的胃),但我不确定答案是否重要. 您可以直接从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,I] { def ask: WriterT[F,I] = MonadTrans[WriterT[?[_],?]].liftM(F.ask) def local[A](f: I => I)(fa: WriterT[F,A]): WriterT[F,A] = fa.mapT(F.local(f)) def point[A](a: => A): WriterT[F,A] = a.point[WriterT[F,?]] def bind[A,B](fa: WriterT[F,A])( f: A => WriterT[F,B] ): WriterT[F,B] = fa.flatMap(f) } 请注意,我使用的是kind-projector,因为lambda版本的类型将更像Haskell版本的四到五倍而不是三倍. 一旦定义了此实例,就可以编写以下内容: import scalaz.{ Id,ReaderT } import scalaz.std.list._ type P[A] = ReaderT[Id.Id,A] type R[A] = WriterT[P,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") } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |