我已经多次看到 Reader
在野外被使用并带来重大好处。 (一个值得注意的例子是 stack
,built around 是 Reader
的直接衍生品,可以在类型级别告知用户其内容的充足性。) 经过一番思考,我了解到这种好处仅仅是代码结构层面上的,从某种意义上说,Reader
在很多地方所做的只是提供一个参数,到复杂的功能接线。也就是说,我开始相信我们总是可以用 λx 形式的 lambda 抽象来替换持有某些
。这似乎与 official explanations 一致该主张:x
的读取器。 ... x ... x ...
... the partially applied function type (->) r is a simple reader monad ...
但是,从注意到 Reader
是一种分段编写 lambda 抽象的方法,到声称它是一个部分应用函数,还有很长的路要走。
是否存在已应用但未部分应用的函数?它只是一个值:
λ :t id 1 id 1 :: Num a => a λ :t 1 1 :: Num a => a
有没有一个函数甚至没有被部分应用?我们永远不会知道:
λ :t fromMaybe fromMaybe :: a -> Maybe a -> a λ :t flip maybe id flip maybe id :: b -> Maybe b -> b
即使忽略这一点,我也不会相信 (->) r
(为什么不直接写 (r ->)
?) 完全是一个Reader
monad。也许我可以编写一个类型检查的实例。也许它甚至会遵守法律。只要我不认为我的功能是Reader
,只要我没有正确的直觉,它的愿景,它对我来说就同样有用作为四色定理的第一个证明。另一方面,我如何确定这是在函数上定义 monad 的唯一方法? Num
上有多个 Monoid
,List
上至少有两个 Applicative
- 这不是太鲁莽地将函数视为单独的 Reader
monad?
困境并没有结束。当我去寻找答案时,我偶然发现了一个even more puzzling注意:Reader
现在恰好是 hom
仿函数,甚至是一般可表示的仿函数。而来自另一端的人们实际上提前知道 Haskell 中会有这样的构造,甚至拼写它的类型,与上述官方解释中的拼写相同。现在,这超出了我的理解范围,但我可以从 Mac Lane 解析 hom 仿函数的定义。通过一些想象,可以看出,如果将函数 a -> b
作为(假定的)类别 Hask 中的态射,我们可以将其与 组合id
再次获取...函数 a -> b
,这次作为集合 hom(a, b)
的元素。
这与部分应用的某些态射有什么联系吗?或者使用 Reader
作为 stack
中的选项存储?我真的可以看到 hom 仿函数 Hask -> Set 的对象和箭头函数吗? (我将采用一个endofunctor Hask -> Hask作为合理的近似值。)那是我值得信赖的伙伴pure
吗? > 和fmap
?
那么,之后我该如何实际使用 Reader
呢?
最佳答案
我无法回答您的所有问题,但让我们从简单的问题开始:
(->) r
(why not just write(r ->)
?)
因为后者是Haskell中的语法错误。您不能在类型上使用此部分语法。
... claiming that it is a partially applied function.
事情不是这么说的。引用如下:
the partially applied function type
(->) r
is a simple reader monad
这是一个部分应用的类型,而不是一个部分应用的函数。或者换句话说,它是这样解析的:((部分应用)(函数类型))
Haskell 中函数类型的类型构造函数拼写为 ->
.
完全应用的函数类型类似于 r -> a
(或等效 (->) r a
),其中 r
是参数类型且 a
结果类型。
因此(->) r
是 ->
的部分应用(函数类型)。
如果我们忽略 monad 转换器和 ReaderT
, Reader
的简单定义是:
newtype Reader r a = Reader (r -> a)
runReader :: Reader r a -> r -> a
runReader (Reader f) x = f x
-- or rather:
runReader :: Reader r a -> (r -> a)
runReader (Reader f) = f
或等效的:
newtype Reader r a = Reader{ runReader :: r -> a }
即Reader
只是 ->
的新类型(非常薄的 wrapper ),带有 runReader
用于展开。
您甚至可以制作->
MonadReader
的一个实例只需复制 Reader
的实例即可并删除所有 Reader
/runReader
包装/展开。
关于haskell - 一个环境如何恰好是一个部分应用函数,甚至是一个 hom 仿函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49088510/