那么'a here是什么意思?
这类似于函数的参数多态性(在 Java 中称为泛型),但对于类型而言。在这个存储整数的代码集中,类型为int set,字符串---string set等。'a在前面,因为它是常见的OCaml语法。在修改后的语法中,类型变量写在类型名之后:如list int 或set list int。有关不同类型多态性的更多信息,我可以向您推荐一本书Types at programming languages,第五部分:多态性。如果您了解函数的参数多态性,我认为增强您的类型知识并不难。
隐藏了哪些细节?
在您的 ML 文件中,'a set 类型定义为元素列表。要搜索列表中的某个元素,必须遍历列表并为每个元素调用(=)(这是List.mem 函数的工作方式)。 AFAIR 在 OCaml 中,stdlib 集合被实现为平衡树,并且存储在集合中的值应该具有函数 compare: t -> t -> int 其中t 是存储在集合中的元素的类型。
但是集合可以有不同的定义,如果你只看 .mli 中的抽象类型,那么你只能猜测它是如何在 .ml 文件中实现的。
确实,在这个定义中,'a list 类型已经被用来实现'a set 类型,但是从接口文件中,这个信息是不可见的——隐藏的部分是set 类型是真的是list。模块的实现方式以及对外部世界可用的信息的选择,使得程序可以在不知道它是如何制作的情况下使用set 类型。
这是软件设计的一个重要特性,因为它让开发人员无需更改使用它的代码即可更改该模块的实现。使类型抽象强制分离:如果您尝试在模块外部使用list 作为set,则会收到类型错误。
type 'a set = 'a list
AFAIR,这一行引入了一个“类型同义词”(或别名)说:这里和下面的类型 set 与 list 相同,您可以将 set 与期望 list 的函数一起使用,反之亦然反之亦然。
当您看到'a set 时,您应该明白它只是一组东西,当您将string 设置为设置时,它将是string set。如果您看到'a set,您无法说出该集合中存储或将存储的内容,但如果您看到string set,您可以。上面的书中也提到了类型同义词。
附:
所以你的意思是 type 'a set = 'a list 表示该集合期望列表作为参数?
不,它没有。您只需在此行中添加新的类型别名。它不会缩小可以替换为 'a 类型变量的类型的数量。如果你写
# type 'a set = 'a list;;
type 'a set = 'a list
# let create x : _ set = [x];;
val create : 'a -> 'a set = <fun>
然后
List.map ((+)1) (create 2);;
编译器会将create 2 的类型推断为int set(因为create 的'a 类型的参数使用了int 值,并且该函数的返回类型为@987654354 @),然后它会查看其类型别名(同义词)表,当它理解类型 set 与类型 list 相同时,它将继续类型推断的过程。
您应该明白,在创建新同义词时应该编写正确数量的类型变量,即type 'a new_t = ('a*'b) list 对我和编译器都没有任何意义。左边的类型变量应该至少和右边一样多:例如,type ('a, 'b) new_t = ('a * 'b) list 有效。