作者:墙脚等红线_987 | 来源:互联网 | 2023-02-07 01:20
1> Travis Brown..:
我不完全确定Scalaz为什么不提供这个实例(或MonadReader
类似的monad变换器的实例),但我猜这个答案与WriterTInstanceN
已经过去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, 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")
}
}