我把它读作“给定一个需要l ~ r
,返回那个
学期”
它“给定一个术语,其类型包含l
,返回该术语以及所有l
s 被替换为r
s 在类型中”(或在另一个方向r -> l
)。这是一个非常巧妙的技巧,允许您委托所有cong
, trans
, subst
以及与 GHS 类似的内容。
这是一个例子:
{-# LANGUAGE GADTs, DataKinds, PolyKinds, TypeFamilies, TypeOperators, RankNTypes #-}
data Nat = Z | S Nat
data Natty n where
Zy :: Natty Z
Sy :: Natty n -> Natty (S n)
data Vec a n where
Nil :: Vec a Z
Cons :: a -> Vec a n -> Vec a (S n)
type family (n :: Nat) :+ (m :: Nat) :: Nat where
Z :+ m = m
(S n) :+ m = S (n :+ m)
assoc :: Natty n -> Natty m -> Natty p -> (((n :+ m) :+ p) ~ (n :+ (m :+ p)) => t) -> t
assoc Zy my py t = t
assoc (Sy ny) my py t = assoc ny my py t
coerce :: Natty n -> Natty m -> Natty p -> Vec a ((n :+ m) :+ p) -> Vec a (n :+ (m :+ p))
coerce ny my py xs = assoc ny my py xs
UPDATE
专业化很有启发assoc
:
assoc' :: Natty n -> Natty m -> Natty p ->
(((n :+ m) :+ p) ~ (n :+ (m :+ p)) => Vec a (n :+ (m :+ p)))
-> Vec a (n :+ (m :+ p))
assoc' Zy my py t = t
assoc' (Sy ny) my py t = assoc ny my py t
coerce' :: Natty n -> Natty m -> Natty p -> Vec a ((n :+ m) :+ p) -> Vec a (n :+ (m :+ p))
coerce' ny my py xs = assoc' ny my py xs
丹尼尔·瓦格纳解释了评论中发生的事情:
或者,换句话说,您可以将 ((l ~ r) => t) -> t 读作“给定
假设 l ~ r 的输入良好的术语,返回相同的术语
从我们已经证明 l ~ r 并排除了这一点的背景来看
假设”。
我们来详细说明一下证明部分。
In the assoc' Zy my py t = t
case n
等于Zy
因此我们有
((Zy :+ m) :+ p) ~ (Zy :+ (m :+ p))
这减少到
(m :+ p) ~ (m :+ p)
这显然是恒等式,因此我们可以解除该假设并返回t
.
在每个递归步骤中,我们维护
((n :+ m) :+ p) ~ (n :+ (m :+ p))
方程。所以当assoc' (Sy ny) my py t = assoc ny my py t
方程变为
((Sy n :+ m) :+ p) ~ (Sy n :+ (m :+ p))
这减少到
Sy ((n :+ m) :+ p) ~ Sy (n :+ (m :+ p))
由于定义(:+)
。由于构造函数是单射的
constructors_are_injective :: S n ~ S m => Vec a n -> Vec a m
constructors_are_injective xs = xs
方程变为
((n :+ m) :+ p) ~ (n :+ (m :+ p))
我们可以打电话assoc'
递归地。
终于在号召下coerce'
这两个术语是统一的:
1. ((n :+ m) :+ p) ~ (n :+ (m :+ p)) => Vec a (n :+ (m :+ p))
2. Vec a ((n :+ m) :+ p)
Clearly Vec a ((n :+ m) :+ p)
is Vec a (n :+ (m :+ p))
假设((n :+ m) :+ p) ~ (n :+ (m :+ p))
.