包含一个模块吞下它的类型

时间:2017-09-08 17:52:57

标签: types module ocaml

我有以下内容:

Person模块类型,包含获取名字和姓氏的方法:

module type Person = sig
  type t
  val first : t -> string
  val last : t -> string
end

使用PersonUtils函数扩展Person的{​​{1}}仿函数:

name

module PersonUtils (Person: Person) : sig type t val name : t -> string end = struct include Person let name p = Person.first p ^ " " ^ Person.last p end 模块如下:

Main

module Main : sig type t val name : t -> string end = struct include PersonUtils(struct type t = { first: string; last: string; } let first p = p.first let last p = p.last end) end 中,我想添加一个额外的Main函数:所以我将以下内容添加到签名和模块中:

loud_first_name

但是,似乎module Main : sig type t val name : t -> string (* New *) val loud_first_name : t -> string end = struct include PersonUtils(struct type t = { first: string; last: string; } let first p = p.first let last p = p.last end) (* New *) let loud_first_name p = String.uppercase p.first end 不再知道我的类型loud_first_name的结构,所以我留下了错误t

我的问题是:我如何创建像Unbound record field first这样的方法,以便他们仍然可以访问我的记录字段?我试图将loud_first_name类型提升到一个级别,但在我的仿函数的参数中使用它时遇到了麻烦。

t

2 个答案:

答案 0 :(得分:1)

看起来像是type nonrec t = t(感谢Étienne Millon)并将模块与签名组合在一起修复了我的问题。

module type PUSig = sig
  type t
  val name : t -> string
end

module PersonUtils (Person: Person) : PUSig with type t = Person.t = struct
  include Person
  let name p = Person.first p ^ " " ^ Person.last p
end

module Main : sig
  type t = {
    first: string;
    last: string;
  }
  val loud_first_name : t -> string
end = struct
  type t = {
    first: string;
    last: string;
  }

  include (PersonUtils(struct
             type nonrec t = t
             let first p = p.first
             let last p = p.last
           end) : PUSig with type t := t)

  (* New *)
  let loud_first_name p = String.uppercase_ascii p.first
end

答案 1 :(得分:0)

您必须在签名中注明您的类型是相同的,如果您只在结构中指明,则信息将会丢失。

module PersonUtils (Person: Person) : sig
  type t = Person.t
  val name : t -> string
end
 = struct
  include Person
  let name p = Person.first p ^ " " ^ Person.last p
end

另一种方法(我建议)是在模块类型声明中添加with子句。

module PersonUtils (Person: Person) : sig
  type t
  val name : t -> string
end
with type t = Person.t
 = struct
  include Person
  let name p = Person.first p ^ " " ^ Person.last p
end

虽然签名声明中没有直接显示这些信息,但它允许您单独声明您的签名和您的仿函数:

module type Personutils_T = sig
  type t
  val name : t -> string
end

module PersonUtils (Person: Person) : Personutils_T
with type t = Person.t
 = struct
  include Person
  let name p = Person.first p ^ " " ^ Person.last p
end