在Haskell中展现这种类型的理由是什么?

时间:2016-03-02 15:22:40

标签: haskell types unfold

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]

2 个答案:

答案 0 :(得分:12)

类型为

的函数
(a -> Maybe a) -> a -> [a]

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

答案 1 :(得分:4)

利用一些理论,人们可以恢复递归类型的折叠/展开类型,包括列表,理解它们的原因。

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)

为了处理类型上的固定点,我们需要从posets切换到类别,这使得一切都更复杂。非常非常粗略地说,每个<=都被一些态射取代。例如,F(U)<=U现在意味着存在一些态射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派生于coinduction原则,它处理最大的后缀点T(成为代数)

(U <= F(U)) ==> (U <= T)