我正在阅读monad 层包的文档 http://hackage.haskell.org/package/layers-0.1/docs/Documentation-Layers-Overview.html我的大脑快要沸腾了。
In the mmtl
作者谈论的本文档部分不变函子。是方法invmap
就好像fmap
of Functor
但它需要逆态射(b -> a)
还。我明白作者为什么这么说hoist
of MFunctor
比tmap
of Invariant
但我不明白逆态射有什么意义。
有没有任何例子Invariant
这不能是一个实例Functor
?
这是一个标准的地方Invariant
出现了——用于嵌入 lambda 演算的高阶抽象语法 (HOAS)。在 HOAS 中,我们喜欢编写表达式类型,例如
data ExpF a
= App a a
| Lam (a -> a)
-- ((\x . x) (\x . x)) is sort of like
ex :: ExpF (ExpF a)
ex = App (Lam id) (Lam id)
-- we can use tricky types to make this repeat layering of `ExpF`s easier to work with
我们希望这种类型具有如下结构Functor
但遗憾的是,自从Lam
has a
s 处于正位置和负位置。所以我们定义
instance Invariant ExpF where
invmap ab ba (App x y) = App (ab x) (ab y)
invmap ab ba (Lam aa) = Lam (ab . aa . ba)
这真的很悲惨,因为我们真正想做的就是折叠它ExpF
输入自身以形成递归表达式树。如果它是一个Functor
这是显而易见的,但由于它不是,我们得到了一些非常丑陋、具有挑战性的结构。
要解决此问题,您可以添加另一个类型参数并将其称为参数化 HOAS
data ExpF b a
= App a a
| Lam (b -> a)
deriving Functor
我们最终发现我们可以使用它的类型在这种类型之上构建一个免费的 monadFunctor
绑定是变量替换的实例。很不错!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)