加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

如何在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")
  }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读