可以使用foldr重写任何递归定义吗?

时间:2015-08-14 17:21:09

标签: haskell functional-programming fold

假设我在haskell中有一个通用的递归定义,如下所示:

foo a0 a1 ... = base_case
foo b0 b1 ...          
    | cond1 = recursive_case_1
    | cond2 = recursive_case_2
    ...

是否可以使用foldr重写?可以证明吗?

2 个答案:

答案 0 :(得分:3)

在类型理论中,确实可以通过依赖模式匹配 详细说明所有定义,只使用消除器(更强类型的fold版本,列表的推广' foldr)。

参见例如Eliminating Dependent Pattern Matching (pdf)

答案 1 :(得分:3)

如果我们按字面解释您的问题,我们可以写const value foldr来实现任何value,正如@DanielWagner在评论中指出的那样。

一个更有趣的问题是我们是否可以禁止Haskell的一般递归,并且" recurse" 通过与每个用户定义的数据类型相关联的消除器/ catamorphisms,这是foldr到归纳定义的数据类型的自然概括。这基本上是(高阶)原始递归。

执行此限制时,我们只能组合终止功能(消除器)。这意味着我们不能再定义非终止函数。

作为第一个例子,我们失去了琐碎的递归

f x = f x
-- or even
a = a

因为,如上所述,语言变得完全。

更有趣的是,一般定点算子丢失了。

fix :: (a -> a) -> a
fix f = f (fix f)

一个更有趣的问题是:我们可以在Haskell中表达的函数怎么样?我们确实失去了所有非全部功能,但我们是否会丢失所有功能?

可计算性理论指出,由于语言变得完全(不再是非终止),我们甚至会在整个片段上失去表达能力。

证明是标准对角化论证。修复总片段中任何程序的枚举,以便我们可以说{&#34} i - 程序"。 然后,让eval i x成为在自然i上运行x个程序作为输入的结果(为简单起见,假设这个类型很好,结果很自然) 。请注意,由于语言是total,因此结果必须存在。此外,eval可以用不受限制的Haskell语言实现,因为我们可以在Haskell中编写Haskell的解释器(左边作为练习:-P),这对于片段来说效果很好。然后,我们只需要

f n = succ $ eval n n

以上是总函数(总函数的组合),它可以用Haskell表示,但不能用片段表示。实际上,否则会有一个计算它的程序,比如i个程序。在这种情况下,我们会有

eval i x = f x

适用于所有x。但是,

eval i i = f i = succ $ eval i i

这是不可能的 - 矛盾。 QED。