Monad值(Reader monad)是从环境到值的函数。界限 函数应用于绑定值,并且都可以访问 共享环境。
但是,为什么有必要在这个monad中使用一个函数(而不是,例如,两个变量,一个用于环境,一个用于值)?
答案 0 :(得分:10)
读者monad的目的是在某些环境中建模依赖的值。或者,如果您愿意,使用"隐式"进行计算。输入。这与沿其环境存储的值不同。
考虑一下:
newtype Reader s a = Reader (s -> a)
ask :: Reader a a
ask = Reader (\s -> s)
这里的价值和环境是一样的。以上简单的"得到"来自环境的价值并将其返回。
相比之下,
newtype Reader s a = Reader (s, a)
ask :: Reader a a
ask = Reader (s, s)
where s = ???
这里我们需要产生环境和价值。但我们没有实际的方法来做到这一点!环境从第一个例子中的输入转变为输出 - 这使得实现ask
成为不可能。
答案 1 :(得分:4)
更多数学论证:
考虑修改环境时会发生什么。例如,假设您的环境中包含Int
,但您的Reader
需要Integer
。即,你有
yourReader :: Reader Integer A
嗯,显然你可以转换环境中的Int
,只需使用
fromIntegral :: Int -> Integer
但这对你的读者monad意味着你 convert到Reader Int A
,因为只有那种类型适用于原始环境。
yourReader' :: Reader Int A
yourReader' = withReader fromIntegral yourReader
数学家在第一个论证中说Reader
是contravariant来描述这一点。但如果它只包含一个值的变量和一个环境的变量,则两个参数中的 co </ b>变量(即Int -> Integer
会将Reader Int A
转换为{{ 1}},而不是相反)。而功能类型在其左侧是逆变的。