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

时间:2015-03-05 08:14:47

标签: haskell 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不同的实际意义是什么?

3 个答案:

答案 0 :(得分:9)

TL; DR

他们是一样的。

一些历史课程

StateWriterReader的灵感来自Mark P. Jones'Functional Programming with Overloading and Higher-Order Polymorphism,他在此定义Reader如下:

  

Reader monad用于允许计算访问所持有的值   在一些封闭环境中(由以下类型r表示)   定义)。

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

作为传递评论,有趣的是要注意这两个功能   只是组合逻辑的标准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

getenv只是askenvlocal . const。因此,该定义已包含Reader的所有重要部分。最终,琼斯定义了monad变换器ReaderTBComp是向后组合):

  

首先,定义两种不同形式的构图是有用的;转发(FComp)和倒退(BComp):

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

[省略Functor,Monad和OutOf实例]

> type ReaderT r = BComp (r ->)

由于StateTWriterT和其他人拥有非转换变体,因此只有Reader r才符合逻辑,这与(->) r完全相同。

无论哪种方式,现在ReaderWriterState都是根据变换器变体定义的,并且您使用各自的Monad*类型类(MonadReader )。

结论

  

所有用法都可以互换吗?

  

这两个Monads的不同之处是什么?

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

答案 1 :(得分:1)

它们都是MonadReader class的实例。所以是的,你可以使用一个而不是另一个。

答案 2 :(得分:0)

事实上它们完全相同。 我们可以通过它们之间的映射使它更正式: toArrow :: Reader r a -> r -> atoReader :: (r -> a) -> Reader r a 实施toReader = ReadertoArrow = runReader

编辑:Reader背后的语义是它拥有一些只读配置,您可以通过您的计算链进行操作。 当你想要传递一些配置信息时,你应该总是更喜欢Reader使用普通箭头类型,因为它是提供有用辅助函数的非常通用接口的一部分,用于操作MonadReaderReader {1}}类似于数据类型,ReaderT用于堆叠Monad s。