22

这个问题说明了一切,真的。我知道(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(反之亦然)

假设我只想使用replicateMfrom Scalaz

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从 a 中读取一个值,而不是拥有a 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实际上能给我带来什么好处。

4

3 回答 3

8

Monad Transformers 用于组合/扩展 monad(将一个 monad 的功能添加到另一个)。例如, (Reader Transformer)用能力ReaderT丰富给定的 monad (将给定的 monad 转换为 Reader,保留 的原始特征)。MReaderM

同时,Monad Transformers 是具有 、 和其他操作的普通bindmonad return

您可以在Scalaz中找到 monad 转换器的示例- 例如,用于ReaderState monad。

于 2011-02-21T13:44:56.557 回答
8

Monad 转换器是类型函数,当应用于 monad 类型时,会生成一个新的 monad,它结合了两个组件的行为。

例如在xmonad窗口管理器中,计算在内部运行:

newtype X a = X (ReaderT XConf (StateT XState IO) a)

也就是说,aReader由 aState和一个IOmonad 组成。

  • Reader允许访问只读存储器
  • State提供一种形式的读写状态
  • IO允许任意外部效果

请注意,monad 转换因此是更高等级的类型。它们采用一种单子类型 ( * -> *),并产生一种新类型。

和往常一样,Haskell wiki 有一些有用的内容:

一切开始的地方:

于 2011-04-24T17:16:41.430 回答
1

我不认为 Reader 用于从文件中读取值。很确定它是用来读取配置值的。我认为它是全局变量、静态变量或动态/线程局部变量(在 Common Lisp 中称为“特殊变量”,有时在 Scheme 中称为“fluid-let”的流体变量)的替代品。因此,使用 Reader/ReaderT 而不是访问全局或动态变量,而不是将参数传递给可能需要访问某些配置选项的每个方法。当某些非常深的代码突然需要访问新的配置选项时,这可能很有用。您可以从您的 main() 函数中传递选项,偷偷地访问全局或使用 Reader/ReaderT。

于 2011-02-23T03:43:51.723 回答