这篇文章涉及到OCaml中的类型定义,我发现以下语法让人感到困惑:
type 'a t
用通俗易懂的语言来解释是什么意思?
type 'a t
用通俗易懂的语言来解释是什么意思?
由于OP有C++语言的经验,我认为以下解释可能会有用。形式为:
type 'a t
与C++接近
template <typename a> class t;
'a list
是一个通用列表,'a
是元素的类型。为了简洁起见,我们使用单个 '
,而不是 template <typename _>
构造。在 OCaml 中,我们使用术语“参数多态性”,而不是“通用编程”。而且,我们说类型构造器而不是模板。后者有一个有趣的结果。就像在 C++ 中,模板实例化创建类型的新实例一样,在 OCaml 中,将多态类型的类型变量具体化会创建一个新类型,例如 int list
,float list
(与 list<int>
,float<list>
相比)。因此,可以将类型构造器 'a list
视为类型级别上的一元函数,它接受一种类型并创建一种类型。可能存在多元类型构造器,例如 type ('key, 'value) hashtbl
是一个二元类型构造器,它为给定的 key
和 value
对创建一种类型。此外,我们可以将非参数类型视为零元类型构造器,因此 int
构造类型 int
。
P.S. F# 语言是 OCaml 的一个后代,允许以两种形式编写:int t
和 t<int>
P.P.S. 为了防止可能的混淆,我想声明,虽然模板和参数类型试图解决相同的问题,但它们仍然有一些区别。模板在实例化后进行类型化,而参数类型在之前进行类型化。因此,参数类型 'a t
被定义为对于所有的 'a
。如果要创建一个类型,其中类型变量没有普遍量化,可以使用另一种机制 - 函数子。它们也非常接近模板,但它们接受类型加上类型要求,这是 C++ 中的概念。概念在 OCaml 的模块类型中具体化,因此函数子实际上是模块级别上的函数,因为它接受一个模块并生成一个模块。
这是一个参数化类型声明。
类型声明允许您声明新的数据类型:
type my_type = int * string
let x : my_type = (42,"Sorry for the inconvenience")
type 'a container = 'a * string * 'a
let x : int container = (0, "hello", 1)
let y : string container = ("stack", "over", "flow")
(* a.ml *)
type 'a t = Nil | Cons of 'a * 'a t
let empty = Nil
let add x l = Cons (x,l)
(* and so on... *)
(* a.mli *)
type 'a t
val empty : 'a t
val add : 'a -> 'a t -> 'at
(* and so on... *)
如果在程序的其他部分中想要操作 A.t
类型,你只能通过定义的 empty
、add
和其他函数来实现,而不能直接使用 Nil
和 Cons
。