这个问题说明了一切,真的。我知道(Scala) Monad 看起来像这样:
trait Monad[M[_]] {
def pure[A](a : A) : M[A]
def bind[A, B](ma : M[A], f : A => M[B]) : M[B]
}
Monad Transformer 是什么样的?它们用于什么?
<小时/> 修改即可。 考虑以下REPL会话:如果monad变换器以某种方式装饰具有读取器功能的monad(反之亦然)
假设我只想使用 Scalaz 中的replicateM
;
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> some(4).replicateM[List](2)
res20: Option[List[Int]] = Some(List(4, 4))
现在让我们说,我需要从Option[Int]
读取Int
值,而不是File
:
scala> val f = (_ : java.io.File) => some(1)
f: (java.io.File) => Option[Int] = <function1>
那么,我可以对待这个读者,好像它是一个Monad?
scala> ReaderT(f).replicateM[List](2)
<console>:16: error: value replicateM is not a member of scalaz.ReaderT[Option,java.io.File,Int]
ReaderT(f).replicateM[List](2)
^
呃,不。
道歉,如果这一切看起来都很愚蠢,我只是想了解我File => Option[Int]
ReaderT
中包裹{{1}}可以带给我的可爱之处。
答案 0 :(得分:8)
Monad变形金刚用于组合/扩展monad(将一个monad的功能添加到另一个monad)。例如,ReaderT
(读者变换器)使给定的monad M
具有Reader
能力(将monad变换为Reader,保留M
的原始特征)。
与此同时,Monad变形金刚是具有bind
,return
和其他操作的普通monad。
答案 1 :(得分:7)
Monad变换器是类型函数,当应用于monad类型时,生成一个新的monad,它结合了两个组件的行为。
E.g。在xmonad
窗口管理器中,计算在里面运行:
newtype X a = X (ReaderT XConf (StateT XState IO) a)
即由Reader
和State
monad组成的IO
。
Reader
可以访问只读内存State
提供了一种读写状态IO
允许任意外部效果请注意,monad变换因此是更高级别的类型。它们采用monadic类型(* -> *
),并产生一种新类型。
与往常一样,Haskell wiki有一些有用的内容:
一切都开始了:
答案 2 :(得分:1)
我不认为Reader是用于从文件中读取值。很确定它是用于读取配置值。我认为它是全局变量,静态或动态/线程局部变量的替代品(在Common Lisp中称为“特殊变量”,或者有时在Scheme中使用“流体释放”称为fluide变量)。因此,使用Reader / ReaderT而不是访问全局或动态变量,而不是将参数传递到可能需要访问某些配置选项的每个方法中。当一些非常深的代码突然需要访问新的配置选项时,这可能很有用。您可以从main()函数中传递该选项,偷偷访问全局或使用Reader / ReaderT。