我已经看到了一些用于rank-2多态性的用例(最突出的例子是ST monad),但没有比这更高级别的用例。有谁知道这样的用例?
答案 0 :(得分:30)
我也许可以提供帮助,虽然这种野兽不可避免地有点牵扯。这是我有时用于开发带有绑定和de Bruijn索引的瓶颈语法的模式。
mkRenSub ::
forall v t x y. -- variables represented by v, terms by t
(forall x. v x -> t x) -> -- how to embed variables into terms
(forall x. v x -> v (Maybe x)) -> -- how to shift variables
(forall i x y. -- for thingies, i, how to traverse terms...
(forall z. v z -> i z) -> -- how to make a thingy from a variable
(forall z. i z -> t z) -> -- how to make a term from a thingy
(forall z. i z -> i (Maybe z)) -> -- how to weaken a thingy
(v x -> i y) -> -- ...turning variables into thingies
t x -> t y) -> -- wherever they appear
((v x -> v y) -> t x -> t y, (v x -> t y) -> t x -> t y)
-- acquire renaming and substitution
mkRenSub var weak mangle = (ren, sub) where
ren = mangle id var weak -- take thingies to be vars to get renaming
sub = mangle var id (ren weak) -- take thingies to be terms to get substitution
通常情况下,我会使用类型类来隐藏最糟糕的血腥,但是如果你解开字典,这就是你会发现的。
关键是mangle
是一个排名2操作,它采用了一个概念,在它们工作的变量集中具有多态的合适操作:将变量映射到thingies的操作变成了术语变换器。整个过程展示了如何使用mangle
生成重命名和替换。
以下是该模式的具体实例:
data Id x = Id x
data Tm x
= Var (Id x)
| App (Tm x) (Tm x)
| Lam (Tm (Maybe x))
tmMangle :: forall i x y.
(forall z. Id z -> i z) ->
(forall z. i z -> Tm z) ->
(forall z. i z -> i (Maybe z)) ->
(Id x -> i y) -> Tm x -> Tm y
tmMangle v t w f (Var i) = t (f i)
tmMangle v t w f (App m n) = App (tmMangle v t w f m) (tmMangle v t w f n)
tmMangle v t w f (Lam m) = Lam (tmMangle v t w g m) where
g (Id Nothing) = v (Id Nothing)
g (Id (Just x)) = w (f (Id x))
subst :: (Id x -> Tm y) -> Tm x -> Tm y
subst = snd (mkRenSub Var (\ (Id x) -> Id (Just x)) tmMangle)
我们只执行一次遍历遍历,但是以非常一般的方式,我们通过部署mkRenSub模式(它以两种不同的方式使用一般遍历)来获得替换。
再举一个例子,考虑类型操作符之间的多态操作
type (f :-> g) = forall x. f x -> g x
IMonad
(索引monad)是一些m :: (* -> *) -> * -> *
配备多态运算符
ireturn :: forall p. p :-> m p
iextend :: forall p q. (p :-> m q) -> m p :-> m q
因此这些操作排名第2位。
现在任何由任意索引monad参数化的操作都是3级。所以,例如,构建通常的monadic组合,
compose :: forall m p q r. IMonad m => (q :-> m r) -> (p :-> m q) -> p :-> m r
compose qr pq = iextend qr . pq
一旦解开IMonad
的定义,依赖于3级量化。
故事的道德:一旦你在多态/索引概念上进行更高阶的编程,你的有用工具包的词典就会变成第2级,而你的通用程序会变成第3级。当然,这可能会再次发生升级
答案 1 :(得分:9)
也许是我读过的摘要的最佳结局:"Multiplate only requires rank 3 polymorphism in addition to the normal type class mechanism of Haskell."。 (哦,只有Rank-3多态,没什么大不了的!)