我有以下代码:
module Make_Set (Elt : EQ) : SET with type elt = Elt.t = struct
type elt = Elt.t
type t = elt list
let empty = []
let rec is_element i set =
match set with [] -> false | x :: xs -> Elt.eq x i || is_element i xs
let add i set = if is_element i set then set else i :: set
end
我看不懂
SET with type elt = Elt.t
,在官方文档中也找不到。
模块类型的
with
约束(如手册的教程部分和参考部分中所述)提供了一种通过在类型、模块或模块类型上添加相等性来细化模块类型的方法。
在您的情况下,约束
SET with type elt = Elt.t
读取:通过添加类型SET
是elt
的信息来细化模块类型Elt.t
。
当在函子内构建从其他类型派生的类型时,这特别有用。 例如,让我们考虑一个小型模块类型
SHOWABLE
module type SHOWABLE = sig
type t
val show: t -> string
end
指定提供类型
t
和函数 show
的模块,该函数将此类型转换为字符串表示形式。
例如,该规范的实现可以是:
module Int_showable = struct
type t = int
let show = string_of_int
end
然后,如果我们有两个满足
SHOW
规范的模块,我们可以构建一个 Pair
模块,该模块从一对 SHOWABLE
构建一个 SHOWABLE
模块
模块:
module PAIR(X:SHOWABLE)(Y:SHOWABLE) = struct
type t = X.t * Y.t
let show (x,y) = String.concat "" ["(";X.show x;", "; Y.show y; ")"]
end
但是生成的模块的类型是什么?
有人可能会忍不住回答
SHOWABLE
。
但如果我们直接使用这个模块类型
module Pair(X:SHOWABLE)(Y:SHOWABLE): SHOWABLE = struct
type t = X.t * Y.t
let show (x,y) = String.concat "" ["("; X.show x; ", "; Y.show y; ")"]
end
module Int_Pair = Pair(Int_showable)(Int_showable)
一旦我们尝试使用
Int_pair
模块,就会遇到类型错误:
let fail = Int_pair.show (1,2)
我们收到错误
Error: This expression has type 'a * 'b but an expression was expected of type
Int_pair.t
因为约束
module Pair(X:SHOWABLE)(Y:SHOWABLE): SHOWABLE
将
PAIR
的结果限制为恰好是 SHOWABLE
。在模块类型SHOWABLE
中,类型t
是抽象的,其他所有关于该类型的具体信息都已被删除,我们不再知道Int_pair.t
实际上是int * int
。
因此我们需要一种方法来描述模块类型,即
SHOWABLE
,只不过类型 t
应该是一对 X.t
和 Y.t
。
当然,我们可以直接写成:
module Pair(X:SHOWABLE)(Y:SHOWABLE): sig
type t = X.t * Y.t
val show: t -> int
end = ...
但是将来的阅读可能不会发现生成的模块也满足
SHOWABLE
规范的事实。
with type
约束是此问题的解决方案,它提供了一种通过重写类型定义来修补先前模块类型的方法:
module type SHOWABLE_INT = SHOWABLE with type t = int
可以读作:
SHOWABLE_INT
除了SHOWABLE
之外就是type t = int
。换句话说,SHOWABLE_INT
是
module type SHOWABLE_INT = sig
type t = int
val show: t -> int
end
这为我们提供了一种简单的方法来写下
Pair
函子的类型:
module Pair(X:SHOWABLE)(Y:SHOWABLE): SHOWABLE with type t = X.t * Y.t = ...
一旦我们添加了正确的类型相等性,之前的错误就消失了:
module Int_Pair = Pair(Int_showable)(Int_showable)
let ok = Int_pair.show (1,2)
并且
ok
绑定到 "(1, 2)"
。
我肯定可以在官方文档中找到,但对初学者更友好的是“Real World OCaml”的相应第11章。这本书从 2022 年开始有新版本。