在datatype
声明中,如果所有变体的所有类型参数都是eqtype
s,则标准ML将生成相等类型。
我在一些地方看过评论,哀叹用户无法提供自己的平等定义,并构建自己的方法和SML规则的意外后果(例如裸ref
和{{1} s是eqtypes,但array
不是eqtype。
来源:http://mlton.org/PolymorphicEquality
人们可能希望能够比较两个类型为real的值,因为ref单元格上的指针比较就足够了。不幸的是,类型系统只能表示用户定义的数据类型是否允许相等。
我想知道是否可以阻止 eqtyping。比如说,我正在将一个集合实现为一个二元树(带有一个不必要的变体),我想要保证在结构上比较集合的能力。
datatype Foo = Foo of (real ref)
假设我不希望人们能够将datatype 'a set = EmptySet | SetLeaf of 'a | SetNode of 'a * 'a set * 'a set;
和SetLeaf(5)
与SetNode(5, EmptySet, EmptySet)
区分开来,因为这是一个破坏抽象的操作。
我尝试使用=
的一个简单示例,看看我是否可以使用签名将类型降级为非eqtype。
datatype on = On | Off
似乎透明归属无法阻止(* attempt to hide the "eq"-ness of eqtype *)
signature S = sig
type on
val foo : on
end
(* opaque transcription to kill eqtypeness *)
structure X :> S = struct
datatype on = On | Off
let foo = On
end
成为eqtype,但不透明的归属确实阻止了它。但是,这些解决方案并不理想,因为它们引入了一个新模块并隐藏了数据构造函数。有没有办法阻止自定义类型或类型构造函数成为X.on
或允许相等而不隐藏其数据构造函数或引入新模块?
答案 0 :(得分:6)
简短的回答是否定的。当类型的定义可见时,它的等式是定义所暗示的。阻止它为eq的唯一方法是调整定义,例如,通过添加一个带有real
参数的伪构造函数。
顺便说一下,小修正:你的类型foo
应该是一个相等的类型。如果您的SML实现不同意,那么它就有错误。当real bar
(这是MLton手册讨论的内容)时,另一种情况是datatype 'a bar = Bar of 'a ref
。第一个工作但第二个不工作的原因是ref
在SML中是神奇的:它具有用户类型不能拥有的多态性等形式。