在F#中实现幻像类型 [英] Implementing phantom types in F#

查看:70
本文介绍了在F#中实现幻像类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Ocaml程序员可以使用所谓的幻像类型"来使用类型系统强制执行某些约束.可以在 http://ocaml.janestreet.com/?q=node/11 .

Ocaml programmers can use so called 'phantom types' to enforce some constraints using the type system. A nice example can be found at http://ocaml.janestreet.com/?q=node/11.

语法type readonly在F#中不起作用.可以将其替换为定义为type readonly = ReadOnlyDummyValue的伪幻像类型,以实现上述博客文章中的技巧.

The syntax type readonly doesn't work in F#. It could be replaced with a pseudo-phantom type defined as type readonly = ReadOnlyDummyValue in order to implement the tricks in the above mentioned blog post.

是否有更好的方法在F#中定义幻像类型?

Is there a better way to define phantom types in F#?

推荐答案

我认为仅使用type somename定义类型在F#中不起作用. F#编译器需要从声明中生成一些.NET类型,并且F#规范没有明确定义幻像类型应该发生什么.

I think that defining type just using type somename won't work in F#. The F# compiler needs to generate some .NET type from the declaration and F# specification doesn't explicitly define what should happen for phantom types.

您可以在实现文件(.fs)中创建具体类型(例如,使用type somename = ReadOnlyDummyValue),并通过仅在接口文件(.fsi)中添加type somename来隐藏该类型的内部.这样,您就可以很接近幻像类型-文件外部的用户将看不到该类型的内部.

You can create a concrete type (e.g. with type somename = ReadOnlyDummyValue) in the implementation file (.fs) and hide the internals of the type by adding just type somename to the interface file (.fsi). This way you get quite close to a phantom type - the user outside of the file will not see internals of the type.

另一个吸引人的选择是使用接口.这对我来说听起来很合逻辑,因为空接口可能是您可以声明的最简单的类型(并且不引入任何虚拟标识符).空界面如下所示:

Another appealing alternative would be to use interfaces. This sounds logical to me, because empty interface is probably the simplest type you can declare (and it doesn't introduce any dummy identifiers). Empty interface looks like this:

type CanRead = interface end
type CanWrite = interface end

在这种情况下,有趣的是,您还可以创建继承的接口:

The interesting thing, in this case, is that you can also create inherited interfaces:

type CanReadWrite = 
  inherit CanRead
  inherit CanWrite

然后,您可以编写一个函数,该函数可以使用Ref<CanRead, int>类型的值,但也可以使用Ref<CanReadWrite, int>类型的值(因为这些值也支持读取):

Then you can write a function that can take values of type Ref<CanRead, int> but also values of type Ref<CanReadWrite, int> (because these values also support reading):

let foo (arg:Ref<#CanRead, int>) = // ...    

这似乎很有用.我真的很感兴趣是否也可以在OCaml中完成(因为它依赖于F#对接口和继承的支持).

This seems like something that could be useful. I would be actually quite interested whether this can be done in OCaml too (because it relies on the F# support for interfaces and inheritance).

这篇关于在F#中实现幻像类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆