Ocaml程序员可以使用所谓的“幻像类型”来使用类型系统强制执行某些约束。可以在http://ocaml.janestreet.com/?q=node/11找到一个很好的例子。
语法type readonly
在F#中不起作用。它可以替换为定义为type readonly = ReadOnlyDummyValue
的伪幻像类型,以便在上述博客文章中实现技巧。
有没有更好的方法来定义F#中的幻像类型?
答案 0 :(得分:15)
我认为仅使用type somename
定义类型在F#中不起作用。 F#编译器需要从声明中生成一些.NET类型,而F#规范没有明确定义幻像类型应该发生什么。
您可以在实现文件(.fs)中创建具体类型(例如,使用type somename = ReadOnlyDummyValue
),并通过仅将type somename
添加到接口文件(.fsi)来隐藏该类型的内部。这样你就会非常接近幻像类型 - 文件外部的用户将看不到该类型的内部。
另一个吸引人的选择是使用接口。这对我来说听起来很合乎逻辑,因为空接口可能是您可以声明的最简单类型(并且它不会引入任何虚拟标识符)。空接口看起来像这样:
type CanRead = interface end
type CanWrite = interface end
有趣的是,在这种情况下,您还可以创建继承的接口:
type CanReadWrite =
inherit CanRead
inherit CanWrite
然后你可以编写一个函数,它可以获取Ref<CanRead, int>
类型的值,但也可以编写Ref<CanReadWrite, int>
类型的值(因为这些值也支持读取):
let foo (arg:Ref<#CanRead, int>) = // ...
这似乎是有用的东西。我真的很感兴趣是否可以在OCaml中完成(因为它依赖于F#支持接口和继承)。