假设我在haskell中有一个通用的递归定义,如下所示:
foo a0 a1 ... = base_case
foo b0 b1 ...
| cond1 = recursive_case_1
| cond2 = recursive_case_2
...
是否可以使用foldr重写?可以证明吗?
答案 0 :(得分:3)
在类型理论中,确实可以通过依赖模式匹配 详细说明所有定义,只使用消除器(更强类型的fold
版本,列表的推广' foldr
)。
答案 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。