4

文档中给出的示例unfoldr :: (b -> Maybe (a, b)) -> b -> [a]

unfoldr (\b -> if b == 0 then Nothing else Just (b, b-1)) 10

可以很容易地用冗余对编写:

unfoldr (\b -> if b == 1 then Nothing else Just (b-1, b-1)) 11

unfoldr需要这对做什么(a,b)?为什么它的类型不是(a -> Maybe a) -> a -> [a]

4

2 回答 2

13

带类型的函数

(a -> Maybe a) -> a -> [a]

将输出列表元素类型限制为与通过生成过程线程化的状态相同。unfoldr更通用的是它允许使用独立类型的状态。

于 2016-03-02T15:27:19.363 回答
4

利用一些理论,可以恢复递归类型的折叠/展开类型,包括列表,了解它们为什么是它们。

设为A固定类型。类型“ As 的列表”满足同构

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)<=Unow 表示存在某种态射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)
于 2016-03-02T18:31:40.580 回答