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 -> a
和 toReader :: (r -> a) -> Reader r a
实现 toReader = Reader
和 toArrow = runReader
.
编辑:Reader
背后的语义是它包含一些只读配置,您可以通过您的计算链进行线程化。
当你想要线程一些配置信息时,你应该总是更喜欢 Reader
而不是使用普通箭头类型,因为它是提供有用辅助函数的非常通用的接口的一部分, MonadReader
class 用于操作 Reader
之类的数据类型以及 ReaderT
用于堆叠 Monad
s.
TL;DR
他们是一样的。
一些历史课
State
、Writer
和 Reader
的灵感来自 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
就是ask
,env
就是local . const
。因此,这个定义已经包含了Reader
的所有重要部分。最终,琼斯定义了 monad 转换器 ReaderT
(BComp
是反向组合):
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 ->)
因为StateT
、WriterT
和其他人有他们的非变形变体,所以有一个Reader r
是合乎逻辑的,这实际上和[=36=一样].
无论哪种方式,如今 Reader
、Writer
和 State
是根据它们的转换器变体定义的,并且您使用它们各自的 Monad*
类型类(MonadReader
).
结论
So are they interchangeable in all usages?
是的。
And what's the actual significance of differing these two Monads?
None, 除了 ReaderT
实际上是一个 monad 转换器,这让事情变得更简单。
了解到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 -> a
和 toReader :: (r -> a) -> Reader r a
实现 toReader = Reader
和 toArrow = runReader
.
编辑:Reader
背后的语义是它包含一些只读配置,您可以通过您的计算链进行线程化。
当你想要线程一些配置信息时,你应该总是更喜欢 Reader
而不是使用普通箭头类型,因为它是提供有用辅助函数的非常通用的接口的一部分, MonadReader
class 用于操作 Reader
之类的数据类型以及 ReaderT
用于堆叠 Monad
s.
TL;DR
他们是一样的。
一些历史课
State
、Writer
和 Reader
的灵感来自 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 typer
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
andS
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
就是ask
,env
就是local . const
。因此,这个定义已经包含了Reader
的所有重要部分。最终,琼斯定义了 monad 转换器 ReaderT
(BComp
是反向组合):
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 ->)
因为StateT
、WriterT
和其他人有他们的非变形变体,所以有一个Reader r
是合乎逻辑的,这实际上和[=36=一样].
无论哪种方式,如今 Reader
、Writer
和 State
是根据它们的转换器变体定义的,并且您使用它们各自的 Monad*
类型类(MonadReader
).
结论
So are they interchangeable in all usages?
是的。
And what's the actual significance of differing these two Monads?
None, 除了 ReaderT
实际上是一个 monad 转换器,这让事情变得更简单。