这是一个证明的草图。
鉴于程序的大小必须是有限的,程序中定义的所有类型必须只包含有限多个成员,并且只能引用有限多个其他类型。这同样适用于任何程序入口点和在程序初始化之前定义的任何对象。
在没有连续数组的情况下(它是具有运行时自然数的类型的乘积,因此大小不受限制),所有类型都必须通过上述类型的组合来获得;类型的派生(pointer-to-pointer-to- )仍然受到程序大小的限制。除了连续数组之外,没有其他工具可以用类型组合运行时值。A
这有点争议;如果例如映射被认为是原始的,那么可以使用其键是自然数的映射来近似数组。当然,任何映射的实现都必须使用自引用数据结构(B 树)或连续数组(哈希表)。
接下来,如果类型是非递归的,那么任何类型链(A
引用B
引用C
...)都必须终止,并且长度不能大于程序中定义的类型数。因此,程序可引用的数据的总大小限制为每种类型的大小乘以程序中定义的名称数量(在其入口点和静态数据中)的乘积。
即使函数是递归的也是如此(严格来说,这违反了对递归类型的禁令,因为函数是类型);在程序中的任何一点立即可见的数据量仍然限于每种类型的大小乘以该点可见名称的数量的乘积。
一个例外是,如果您将“容器”存储在递归函数调用堆栈中;但是,这样的程序将无法在不展开堆栈并且必须重新读取数据的情况下随机遍历其数据,这有点失格。
最后,如果可以动态创建类型,则上述证明不成立;例如,我们可以创建一个 Lisp 样式的列表结构,其中每个单元格都是不同的类型:cons<4>('h', cons<3>('e', cons<2>('l', cons<1>('l', cons<0>('o', nil)))))
. 这在大多数静态类型语言中是不可能的,尽管在某些动态语言中是可能的,例如 Python。