繁体   English   中英

F#:无法隐藏签名中的类型缩写? 为什么不?

[英]F#: Can't hide a type abbreviation in a signature? Why not?

在F#中,我希望得到一个相当标准的抽象数据类型:

// in ADT.fsi
module ADT
  type my_Type

// in ADT.fs
module ADT
  type my_Type = int

换句话说,模块内部的代码知道my_Type是int,但外部代码不是。 但是,F#似乎有一个限制,其中特定的缩写不能被签名隐藏。 此代码给出了编译器错误, 此处描述了限制。

如果my_Type是一个有区别的联合,那么就没有编译器错误。 我的问题是,为什么限制? 我似乎记得能够在SML和Ocaml中做到这一点,而且,在创建抽象数据类型时,这不是一个非常标准的事情吗?

谢谢

正如Ganesh所指出的,这是F#编译器(和.NET运行时)的技术限制,因为在编译期间类型缩写仅被实际类型替换。 因此,如果你写一个函数:

let foo (a:MyType) : MyType = a + 1

编译器将其编译为具有以下签名的.NET方法:

int foo(int a);

如果缩写的实际类型对库的用户是隐藏的,那么他们将无法识别foo函数实际上正在使用MyType (此信息可能存储在某些F#特定的元数据中,但是其他.NET语言无法访问...)。

也许这种限制的最佳解决方法是将类型定义为单个案例区分联合:

type MyType = MT of int
let foo (MT a) = MT(a + 1)

使用这种类型非常方便。 它增加了一些开销(在构造类型的值时会创建新的对象),但在大多数情况下这不应该是一个大问题。

F#中的类型缩写被编译掉(即编译的代码将使用int ,而不是MyType ),因此您无法使它们正确抽象。 理论上,编译器可以在F#世界中强制执行抽象,但这不会非常有用,因为它仍会在其他语言中泄漏。

请注意,您可以在模块中将类型缩写定义为私有:

// File1.fs
module File1
    type private MyType = int 
    let e : MyType = 42
    let f (x:MyType) = x+1

// Program.fs
module Program
do printfn "%A" (File1.f File1.e)

我不清楚为什么你不能用签名隐藏它; 我记录了一个bug来考虑它。

根据我的理解,F#不允许缩写被签名隐藏。

我找到了这个链接 ,博主对此进行了评论,但我不确定为什么会出现这种情况。

我的假设是,这是一种克制,可以在CLR上与其他语言进行更有效的互操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM