不变函子的例子?

时间:2014-02-28 18:49:26

标签: haskell functor

我正在阅读documentation on monad layers package,我的大脑将会沸腾。

在本文档的mmtl部分,作者讨论了不变函子。方法invmapfmap的{​​{1}}类似,但它也需要反态射Functor。我理解为什么作者说(b -> a)的{​​{1}}比hoist的{​​{1}}更强大,但我不明白这种反型态射的重点是什么。

是否有MFunctor的例子不能是tmap的实例?

1 个答案:

答案 0 :(得分:4)

这是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具有a的正面和负面位置都不可能。所以我们定义

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,但由于它不是我们得到一些非常丑陋,具有挑战性的结构。

要解决此问题,请添加另一个类型参数并将其命名为Parametric HOAS

data ExpF b a
  = App a a
  | Lam (b -> a)
  deriving Functor

我们最终发现我们可以使用Functor实例在此类型上构建一个自由monad,其中绑定是变量替换。非常好!