利用一些理论,可以恢复递归类型的折叠/展开类型,包括列表,了解它们为什么是它们。
设为A
固定类型。类型“ A
s 的列表”满足同构
List ~~ Either () (A, List)
可以读作“列表值是一个特殊值(空列表),或者是一个类型的值,A
后跟一个列表值”。
用更简洁的表示法,我们可以写成Either
中缀+
:
List ~~ () + (A, List)
现在,如果我们让F b = () + (A, b)
,我们有
List ~~ F List
上面是一个不动点方程,在使用递归类型时总是会出现。对于由我们定义的任何递归类型,T ~~ F T
我们可以推导出相关折叠/展开的类型(也称为cata/ana
或归纳/共归纳原则)
fold :: (F b -> b) -> T -> b
unfold :: (b -> F b) -> b -> T
在列表的情况下,我们得到
fold :: ((() + (A, b)) -> b) -> List -> b
unfoldr :: (b -> (() + (A, b))) -> b -> List
展开也可以重写,注意Maybe c ~~ () + c
:
unfoldr :: (b -> Maybe (A, b)) -> b -> List
折叠可以改写为
((x + y) -> z) ~~ (x -> z, y -> z)
得到
foldr :: (() -> b, (A, b) -> b) -> List -> b
那么,因为() -> b ~~ b
,
foldr :: (b, (A, b) -> b) -> List -> b
最后,由于(x, y) -> z ~~ x -> y -> z
(currying),我们有
foldr :: b -> ((A, b) -> b) -> List -> b
然后再次:
foldr :: b -> (A -> b -> b) -> List -> b
最后翻转x -> y -> z ~~ y -> x -> z
:
foldr :: (A -> b -> b) -> b -> List -> b
这些类型如何遵循(共)归纳原则?
域理论指出,最小固定点 ( F(T)=T
) 与最小前缀点 ( ) 重合F(T)<=T
,当F
在某个偏序上是单调的。
归纳原理简单地指出,如果T
是最小前缀点,并且F(U)<=U
,那么T<=U
。(证明。它是最少的!。QED。)在公式中,
(F(U) <= U) ==> (T <= U)
为了处理类型上的固定点,我们需要从 poset 切换到类别,这使得一切都变得更加复杂。非常非常粗略地,every<=
被一些态射取代。例如,F(U)<=U
now 表示存在某种态射F U -> U
。“单调F
”意味着它F
是一个函子(因为现在a<=b
暗示F(a)<=F(b)
变成了(a->b)
暗示F a -> F b
)。前缀点是 F 代数 ( F u -> u
)。“最小”变成“初始”。等等。
因此折叠的类型:(暗示也是->
如此)
fold :: (F u -> u) -> (T -> u)
Unfold 源自共归纳原理,该原理处理最大的后缀点T
(成为余代数)
(U <= F(U)) ==> (U <= T)