我很难理解Reader Monad。
编辑:我应该指出一些关于此的资源,而不是试图重复它们。
我以为runReader
只需要一个参数,但现在似乎需要两个参数,一个是存在k (runReader m r)
,另一个是存在r
。
如果您查看 的类型签名runReader :: Reader e a -> e -> a
,则可以将其视为采用 aReader e a
并产生 an e -> a
,或者视为采用 aReader e a
和 ane
并产生 a a
。reader monad 的重点是引入一个隐含的论点。
效果如何runReader (k (runReader m r)) r
?
您可以更详细地说明绑定运算符定义:
instance Monad (Reader e) where
return a = R $ \_ -> a
-- (>>=) :: Reader e a -> (a -> Reader e b) -> Reader e b
ma >>= k = R $ \e -> let a = runReader ma e
mb = k a
in runReader mb e
也就是说,首先 "ma
与e
" (runReader ma :: e -> a
应用于e
) 一起运行。这会产生一个a
.
然后k a
是运行。这会产生一个mb
.
然后 "mb
与e
" (runReader mb :: e -> b
应用于e
) 一起运行。
这被打包成R $ \e -> ... runReader mb e
.
我开始认为理解这一点的困难部分主要与newtype需要对其内容进行不断的包装 ( R
) 和展开 ( runReader
) 的方式有关,而不是臭名昭著的monad 的工作方式。
想象一下,你唯一需要的 monad 就是 reader monad,我们可以不用newtype
andinstance Monad (Reader e)
绒毛。那么您的定义可能如下所示:
type Reader e a = e -> a
-- type Reader e a = (->) e a
-- type Reader e = (->) e
unit :: a -> Reader e a
-- :: a -> (e -> a)
unit a = \_e -> a
-- unit a _e = a
-- unit = const
ask :: Reader e e
-- :: e -> e
ask = \e -> e
-- ask e = e
-- ask = id
bind :: Reader e a -> (a -> Reader e b) -> Reader e b
-- :: (e -> a) -> (a -> (e -> b)) -> (e -> b)
bind ma k = \e -> let a = ma e
mb = k a
in mb e
-- bind ma k e = let mb = k (ma e) in mb e
在这一点上,一切都变得更清楚了,一切unit
都被丢弃e
,一切ask
都被返回e
,并且所做的是接受两个都期望 a 的bind
函数(ma
和k (ma e)
,又名),将它们组合在一个也期望 a 的新函数中,而无需显式在作文过程中通过。mb
e
e
e
在学习如何编写 monad 定义时,我自己的一个误解是它runReader
可以运行任何东西。它帮助我在概念上调用它,unR
因为它所做的只是去除R
包装。