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

Sho*_* Ya 7 monads haskell

我了解到Monad.Reader实际上是一个函数的封装,即:

newtype Reader r a = Reader { runReader :: r -> a }
Run Code Online (Sandbox Code Playgroud)

这是Monad的一个例子,

instance Monad (Reader r) where
    return a = Reader $ \_ -> a
    m >>= k  = Reader $ \r -> runReader (k (runReader m r)) r
Run Code Online (Sandbox Code Playgroud)

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

instance Monad ((->) r) where
    return = const
    f >>= k = \ r -> k (f r) r
Run Code Online (Sandbox Code Playgroud)

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

那么它们在所有用途中都可以互换吗?不同这两个Monads的实际意义是什么?

Zet*_*eta 10

TL; DR

他们是一样的.

一些历史课

State,WriterReader受到Mark P. Jones的" 超载和高阶多态性函数式编程 "的启发,他在此定义Reader如下:

Reader单子用于允许计算访问在一些封闭环境(由类型表示所保持的值r在下面定义).

> instance Monad (r->) where
>     result x = \r -> x
>     x `bind` f = \r -> f (x r) r
Run Code Online (Sandbox Code Playgroud)

作为传递评论,值得注意的是,这两个函数只是组合逻辑的标准KS组合.

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

Reader monads :一类monad,用于描述咨询某些固定环境的计算:

> 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
Run Code Online (Sandbox Code Playgroud)

getenv很简单ask,而且envlocal . const.因此,这个定义已经包含了a的所有重要部分Reader.最终,琼斯定义了monad变换器ReaderT(BComp后向构图):

首先,定义两种不同形式的组合是有用的; 前锋(FComp)和后退(BComp):

> data FComp m n a = FC (n (m a))
> data BComp m n a = BC (m (n a))
Run Code Online (Sandbox Code Playgroud)

[省略Functor,Monad和OutOf实例]

> type ReaderT r = BComp (r ->)
Run Code Online (Sandbox Code Playgroud)

因为StateT,WriterT和其他人有非变压器变体,所以有一个Reader r真正相同的逻辑是合乎逻辑的(->) r.

无论哪种方式,现在Reader,Writer并且State根据它们的变换器变体定义,并且您使用它们各自的Monad*类型类(MonadReader).

结论

那么它们在所有用途中都可以互换吗?

是.

不同这两个Monads的实际意义是什么?

没有,除了ReaderT实际上是一个monad变换器,这使事情变得更容易.