无法在C中添加自然数的后果

时间:2011-12-01 21:23:46

标签: haskell types language-design turing-complete

在系统F中,我可以使用教会数字定义真正的总加法函数。

在Haskell中,由于底值,我无法定义该函数。例如,在haskell中,如果x + y = x,那么我不能说y为零 - 如果x是底部,x + y = x表示任何y。因此,加法不是真正的加法,而是对它的近似。

在C中我无法定义该函数,因为C规范要求所有内容都具有有限的大小。所以在C中,可能的近似值甚至比Haskell更差。

所以我们有:

在System F中,可以定义添加,但不可能有完整的实现(因为没有无限的硬件)。

在Haskell中,不可能定义添加(因为底部),并且不可能有完整的实现。

在C语言中,不可能定义总加法函数(因为所有内容的语义都是有界的),但是可以实现兼容的实现。

因此,所有3个正式系统(Haskell,System F和C)似乎都有不同的设计权衡。

那么选择一个而不是另一个的后果是什么?

3 个答案:

答案 0 :(得分:8)

<强>的Haskell

这是一个奇怪的问题,因为你正在处理=的模糊概念。 _|_ = _|_只在域语义级别“保持”(即使那时你应该真正使用)。如果我们区分域语义级别的可用信息和语言本身的相等性,那么说True ⊑ x + y == x - &gt;是完全正确的。 True ⊑ y == 0

这不是问题的补充,也不是自然数也是问题 - 问题只是区分语言中的相等性和语言语义中的相等或信息的陈述。如果没有底部问题,​​我们通常可以使用天真的等式逻辑推理Haskell。对于底部,我们仍然可以使用等式推理 - 我们只需要使用我们的方程更复杂。

在优秀论文“Fast and Loose Reasoning is Morally Correct”中,更全面,更清晰地阐述了总语言与提升语言所定义的部分语言之间的关系。

<强> C

你声称C要求所有东西(包括可寻址空间)具有有限的大小,因此C语义“对可表示的自然的大小施加限制”。并不是的。 C99 standard表示如下:“任何指针类型都可以转换为整数类型。除了之前指定的, 结果是实现 - 定义。如果结果无法以整数类型表示, 这种行为是未定的。结果不必在任何整数的值范围内 “理由文件进一步强调”C现已在各种架构上实施。其中一些 体系结构具有统一指针,这些指针是最大的某种整数类型的大小 可移植代码不能假设不同指针类型和整数类型之间有任何必要的对应关系。在某些实现中,指针甚至可以比任何整数类型都宽。“

正如您所看到的,显然没有假设指针必须具有有限的大小。

答案 1 :(得分:2)

你有一套理论作为框架来进行推理;有限现实,Haskell语义,系统F只是其中之一。

您可以为自己的工作选择合适的理论,从头开始构建新理论,也可以从聚集在一起的大量现有理论中选择。例如,您可以考虑一组始终终止的Haskell程序并安全地使用无底语义。在这种情况下,您的添加将是正确的。

对于低级语言,可能需要考虑插入有限性,但对于高级语言,省略这些事情是值得的,因为更抽象的理论允许更广泛的应用。

编程时,不使用“语言规范”理论,而使用“语言规范+实现限制”理论,因此在语言规范或语言实现中存在内存限制的情况之间没有区别。当你开始在语言语义框架中构建纯粹的理论结构时,缺乏限制变得很重要。例如,您可能想要证明一些程序等价或语言翻译,并发现语言规范中的每个不需要的细节都会带来很大的证据。

答案 2 :(得分:1)

我确信你听过这样的格言:“从理论上讲,理论与实践没有区别,但在实践中却有。”

在这种情况下,理论上存在差异,但所有这些系统都处理相同数量的可寻址存储器,因此在实践中没有区别。

编辑:

假设您可以在任何这些系统中表示自然数,您可以在任何系统中表示添加。如果您关注的约束阻止您表示自然数,那么您不能代表Nat * Nat添加。

将自然数表示为一对(最大位大小的启发式下界和延迟评估的位列表)。

在lambda演算中,您可以将列表表示为一个函数,该函数返回一个函数,该函数使用true返回1的位,并且使用false调用返回一个函数,该函数对2位执行相同操作等等。

然后添加一个操作应用于传播进位的两个惰性列表的zip。

当然,您必须将最大位大小的启发式表示为自然数,但如果您只实例化的位数严格小于您所代表的数字,并且您的运算符不会破坏该启发式,那么比特大小是一个比你想要操作的数字小的问题,所以操作终止。

在考虑边缘情况的简易性方面,C会给你很少的帮助。您可以返回特殊值来表示溢出/下溢,甚至尝试使它们具有传染性(如IEEE-754 NaN),但如果您未检查,则不会在编译时收到投诉。您可以尝试重载信号SIGFPE或类似陷阱问题。

  

我不能说y为零 - 如果x为底部,x + y = x为任何y。

如果你想进行符号操作,Matlab和Mathematica是用C和C语言实现的。也就是说,python有一个优化的bigint实现,用于所有整数类型。它可能不适合代表非常大的数字。