为什么 Reader monad 存储一个函数?

Why does the Reader monad store a function?

根据 All about monads

Monad values (of the Reader monad) are functions from the environment to a value. The bound function is applied to the bound value, and both have access to the shared environment.

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

reader monad 的要点是对依赖于 某些环境的值建模。或者,如果您愿意,可以使用 "implicit" 输入进行计算。这与存储在其环境中的值不同。

考虑一下:

newtype Reader s a = Reader (s -> a)

ask :: Reader a a
ask = Reader (\s -> s)

这里的值和环境是一样的。上面只是 "gets" 来自环境的值和 returns 它。

相比之下,

newtype Reader s a = Reader (s, a)

ask :: Reader a a
ask = Reader (s, s)
   where s = ???

这里我们既要生产环境,又要生产价值。但是我们没有实际的方法来做到这一点!在第一个示例中,环境从输入变为输出——这使得实现 ask 变得不可能。

一个更数学化的论证:

考虑当您修改 环境时会发生什么。例如,假设您的环境中有一个 Int,但您的 Reader 需要一个 Integer。也就是说,你有

yourReader :: Reader Integer A

嗯,明明可以转换环境里的Int,就用

fromIntegral :: Int -> Integer

但这对你的 reader monad 意味着你 convertReader Int A,因为只有那种类型在你的原始类型中有效环境。

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

数学家通过在其第一个参数中说 Readercontravariant 来描述这一点。但是,如果它只包含一个值变量和一个环境变量,那么它在两个参数中都是 co 变量(即 Int -> Integer 将转换 Reader Int A Reader Integer A,而不是相反)。而函数类型在其左侧是逆变的。