Module 透明签名归属的惊人行为

Module 透明签名归属的惊人行为,module,sml,signature,Module,Sml,Signature,我想定义我自己的抽象类型'a foo,它就像'a ref,是eqtype,即使'a不是。例如: lolcathost% poly Poly/ML 5.5.2 Release > signature FOO = # sig # eqtype 'a foo # val bar : real foo # val qux : real foo # end; signature FOO = sig val bar : real foo type 'a foo val qux : real

我想定义我自己的抽象类型
'a foo
,它就像
'a ref
,是
eqtype
,即使
'a
不是。例如:

lolcathost% poly
Poly/ML 5.5.2 Release
> signature FOO =
# sig
#   eqtype 'a foo
#   val bar : real foo
#   val qux : real foo
# end;
signature FOO = sig val bar : real foo type 'a foo val qux : real foo end
> structure Foo : FOO =
# struct
#   datatype 'a wat = Wat of 'a
#   type 'a foo = 'a wat ref
#   val bar = ref (Wat 0.0)
#   val qux = ref (Wat 0.0)
# end;
structure Foo : FOO
> Foo.bar = Foo.qux;
val it = false: bool
到目前为止,一切都很好!现在:

> !Foo.bar;
val it = Wat 0.0: real wat
> !Foo.qux;
val it = Wat 0.0: real wat
等等。
wat
不应该被隐藏吗?为什么我看到类型为
real wat
的值

wat
不应该被隐藏吗

它是“隐藏的”,因为代码不能引用它;但是,既然你作为一个人意识到了这一点,那么REPL就没有理由回避它

为什么我看到类型为
real wat
的值

为什么不呢?标识符
wat
不在范围内,但类型名称仍然存在。没有理由不存在涉及它的类型的值

(即使没有签名,同样的事情也可能发生;类似于

local
   datatype 'a wat = Wat of 'a
in
   val it = Wat 0.0
end
完全有效,并且具有类似的效果。)

因为我不想让外部代码知道
'a foo
是内部
'a wat ref
,这意味着
!Foo.bar
!Foo.qux
首先不应进行打字检查

如果您不想让外部代码知道
'a foo
是内部
'a wat ref
,那么您不应该使用透明的归属;透明归属的全部意义在于,即使签名没有指定类型,外部代码仍然知道类型是什么(与不透明归属相反,在不透明归属中,外部代码实际上只有签名中指定的类型)

我想定义我自己的抽象类型
'a foo
,它就像
'a ref
,是
eqtype
,即使
'a
不是

不幸的是,这是不可能的。标准ML的定义(修订版)(大部分定义了标准ML'97)在第17页的§4.4“类型和类型功能”中列出了一组精确的相等类型。只有当(1)其类型名及其所有类型参数都承认相等或(2)其类型名是由
ref
表示的类型名时,构造的类型才承认相等。在您的例子中,由于
'a
显然不是一个相等类型,而
foo
不是
ref
'a foo
不承认相等


(注意:我应该提到这里的定义有点错误,因为标准的ML Basis库指定了一些额外的类型名称,这些名称与
ref
具有相同的特殊属性,编译器也实现了这些名称。但是这个扩展只添加了更多的硬编码;它没有为程序员添加任何创建额外类型名称的方法。)这样的类型名称。)

可能
ref
类型不能完全不透明,因为编译器需要知道要分配多少内存以及如何解释存在的位模式。您所展示的内容某种程度上提醒了我,在C中,如果不将空指针强制转换为特定类型,就无法取消对空指针的引用。我不知道它是比wh更奇怪还是更不奇怪在SML/NJ中,当我输入你的定义和类型时,我得到了
val it=Wat 0.0:real?.Foo.Wat
@JohnColeman:我甚至不想让外部代码知道
Foo
是内部引用单元格。我想要一个抽象类型构造函数,恰好与
ref
共享属性th当然,对于要进行类型检查的
!x
x
必须是
a foo
类型的
a foo
,对于某些类型的
a
。因为我不想让外部代码知道
'a foo
是内部
'a wat ref
,这意味着
!foo.bar
>和
!Foo.qux
首先不应进行打字检查。