为什么 Reader monad 存储一个函数?
Why does the Reader monad store a function?
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 意味着你 convert 到 Reader Int A
,因为只有那种类型在你的原始类型中有效环境。
yourReader' :: Reader Int A
yourReader' = withReader fromIntegral yourReader
数学家通过在其第一个参数中说 Reader
是 contravariant 来描述这一点。但是,如果它只包含一个值变量和一个环境变量,那么它在两个参数中都是 co 变量(即 Int -> Integer
将转换 Reader Int A
Reader Integer A
,而不是相反)。而函数类型在其左侧是逆变的。
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 意味着你 convert 到 Reader Int A
,因为只有那种类型在你的原始类型中有效环境。
yourReader' :: Reader Int A
yourReader' = withReader fromIntegral yourReader
数学家通过在其第一个参数中说 Reader
是 contravariant 来描述这一点。但是,如果它只包含一个值变量和一个环境变量,那么它在两个参数中都是 co 变量(即 Int -> Integer
将转换 Reader Int A
Reader Integer A
,而不是相反)。而函数类型在其左侧是逆变的。