无法理解ocaml代码中的语法

问题描述 投票:0回答:2

我有以下代码:

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
,在官方文档中也找不到。

ocaml
2个回答
2
投票

模块类型的

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)"


1
投票

我肯定可以在官方文档中找到,但对初学者更友好的是“Real World OCaml”的相应第11章。这本书从 2022 年开始有新版本。

可以在这里阅读:https://dev.realworldocaml.org/toc.html

© www.soinside.com 2019 - 2024. All rights reserved.