Monad.Reader 和 (->) 单子有什么区别?

What's the difference between Monad.Reader and the (->) monads?

了解到Monad.Reader其实是对一个函数的封装,即:

newtype Reader r a = Reader { runReader :: r -> a }

它是 Monad 的一个实例,

instance Monad (Reader r) where
    return a = Reader $ \_ -> a
    m >>= k  = Reader $ \r -> runReader (k (runReader m r)) r

相比之下,我知道 (->) 也是一个 Monad,

instance Monad ((->) r) where
    return = const
    f >>= k = \ r -> k (f r) r

从定义中可以看出它们实际上的行为完全相同。

那么它们在所有用法中都可以互换吗?区分这两个 Monad 的实际意义是什么?

它们都是MonadReader class的实例。所以是的,你可以用一个代替另一个。

它们实际上是完全一样的。 我们可以通过在它们之间进行映射来使其更正式: toArrow :: Reader r a -> r -> atoReader :: (r -> a) -> Reader r a 实现 toReader = ReadertoArrow = runReader.

编辑:Reader 背后的语义是它包含一些只读配置,您可以通过您的计算链进行线程化。 当你想要线程一些配置信息时,你应该总是更喜欢 Reader 而不是使用普通箭头类型,因为它是提供有用辅助函数的非常通用的接口的一部分, MonadReader class 用于操作 Reader 之类的数据类型以及 ReaderT 用于堆叠 Monads.

TL;DR

他们是一样的。

一些历史课

StateWriterReader 的灵​​感来自 Mark P. Jones 的 Functional Programming with Overloading 和 Higher-Order Polymorphism,其中他定义Reader如下:

A Reader monad is used to allow a computation to access the values held in some enclosing environment (represented by the type r in the following definitions).

> instance Monad (r->) where
>     result x = \r -> x
>     x `bind` f = \r -> f (x r) r

As a passing comment, it is interesting to note that these two functions are just the standard K and S combinators of combinatory logic.

后来,他定义了(几乎)今天的MonadReader

Reader monads : A class of monads for describing computations that consult some fixed environment:

> class Monad m => ReaderMonad m r where
>     env :: r -> m a -> m a
>     getenv :: m r

> instance ReaderMonad (r->) r where
>     env e c = \_ -> c e
>     getenv = id

getenv就是askenv就是local . const。因此,这个定义已经包含了Reader的所有重要部分。最终,琼斯定义了 monad 转换器 ReaderTBComp 是反向组合):

To begin with, it is useful to define two different forms of composition; forwards (FComp) and backwards (BComp):

> data FComp m n a = FC (n (m a))
> data BComp m n a = BC (m (n a))

[omitting Functor, Monad and OutOf instances]

> type ReaderT r = BComp (r ->)

因为StateTWriterT和其他人有他们的非变形变体,所以有一个Reader r是合乎逻辑的,这实际上和[=36=一样].

无论哪种方式,如今 ReaderWriterState 是根据它们的转换器变体定义的,并且您使用它们各自的 Monad* 类型类(MonadReader).

结论

So are they interchangeable in all usages?

是的。

And what's the actual significance of differing these two Monads?

None, 除了 ReaderT 实际上是一个 monad 转换器,这让事情变得更简单。