如何访问OCaml递归模块中定义的类型的字段?

Ste*_*deo 2 recursion ocaml types field module

我正在OCaml中处理递归模块,但在访问类型字段时遇到一些麻烦。

如果我尝试做:

module A = struct type t = { name : string; } end
module A2 = 
  struct 
    include A 
    let getName (x:t) = x.name 
  end;;
Run Code Online (Sandbox Code Playgroud)

一切正常。但是,我需要一个更复杂的类型,这迫使我在递归模块中定义我的类型。

module rec B:Set.OrderedType = 
  struct 
    type t = {name: string; set : S.t} 
    let compare _ _ = 0 
  end 
and S:Set.S = Set.Make (B);;
Run Code Online (Sandbox Code Playgroud)

一切仍然完美。但是,以下模块不正确:

module B2 = 
  struct 
    include B 
    let get_name (x:t) = x.name 
  end;;
Run Code Online (Sandbox Code Playgroud)

返回的错误是“未绑定记录字段名称”。问题是什么 ?

Pas*_*uoq 5

module rec B:Set.OrderedType =

您的递归定义表示该模块B具有签名Set.OrderedType,该签名隐藏了t投影的定义,在本例中为投影。在中Set.OrderedType,类型t是抽象的,如下所示:type t;;

如果要显示type的定义t,则它必须是签名的一部分。第一个示例起作用是因为您没有为module提供签名A,因此默认情况下使用导出所有内容的签名来键入它。

以下示例适用于OCaml 4.02.1。

module rec B: 
sig type t = { name:string ; set : S.t } val compare: t -> t -> int end
=
  struct 
    type t = {name: string; set : S.t} 
    let compare _ _ = 0 
  end 
and S:Set.S = Set.Make (B);;
Run Code Online (Sandbox Code Playgroud)

顶层由此确认定义:

module rec B :
  sig type t = { name : string; set : S.t; } val compare : t -> t -> int end
and S : Set.S
Run Code Online (Sandbox Code Playgroud)