为什么Reader monad存储函数?

时间:2015-10-03 11:28:52

标签: haskell monads

根据 All about monads

  

Monad值(Reader monad)是从环境到值的函数。界限   函数应用于绑定值,并且都可以访问   共享环境。

但是,为什么有必要在这个monad中使用一个函数(而不是,例如,两个变量,一个用于环境,一个用于值)?

2 个答案:

答案 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意味着你 convertReader Int A ,因为只有那种类型适用于原始环境。

yourReader' :: Reader Int A
yourReader' = withReader fromIntegral yourReader

数学家在第一个论证中说Readercontravariant来描述这一点。但如果它只包含一个值的变量和一个环境的变量,则两个参数中的 co <​​/ b>变量(即Int -> Integer会将Reader Int A转换为{{ 1}},而不是相反)。而功能类型在其左侧是逆变的。