同一个引用不能有矛盾类型

若一个共享的引用单元保存空列表,却被概括为可以独立选择任意元素类型,那么一次使用可能写入整数列表,另一次却按布尔列表读出。同一份可变存储因此承担了相互矛盾的类型假设。

问题不在空列表本身,而在创建并共享可变单元之后,仍把每次使用都当成独立的多态实例。需要限制的是这个绑定的泛化方式,而不是取消所有函数或列表的多态。

参考:[1]

用语法近似安全性

SML ’97 将是否允许概括,与右侧表达式是否为非扩张表达式联系起来。常量、变量、函数表达式,以及满足规则的构造子和记录,属于可接受的形式;一般函数应用不能仅凭结果看起来像函数就自动获得同样待遇。

函数表达式的函数体可以在将来调用时执行计算。规则关注绑定当下求值是否可能产生需要共享的效果,并不要求每个函数体都完全不使用可变状态。

参考:[2]

可靠性与表达能力之间

这是一条保守近似规则:某些实际无害的计算也会失去多态,局部使用有时可以进一步确定其单一类型,显式类型说明或调整绑定形式也可能让意图更清楚。

Garrigue 的放宽方案利用类型参数出现的协变位置,恢复一部分本来安全的泛化。不同 ML 系统采用的细节并不相同,所以不能把某一种弱类型变量的显示方式当作所有值限制的定义。

参考:[1] [2]