进一步细化父项签名中嵌套模块的签名

时间:2017-06-10 05:59:11

标签: ocaml

我有一个包含嵌套模块的ML文件。例如:

let f n = n + 1

module type M_type = sig
  val g : int -> int
  val h : int -> int
end

module M : M_type = struct
  let g n = n + 2
  let h n = n + 3
end

let j n = n |> M.h |> M.g |> f

为此ML编写MLI时,我希望不公开M.h,但我希望公开M.g

如下:

module type M_type = sig
  val g : int -> int
end

module M : M_type

val j : int -> int

ML和MLI的上述组合无法编译。

我的想法是我的嵌套模块M包含一些我希望公开给父模块中的其他函数的函数,但不包含父模块的用户。

有没有合法的方法来实现这一目标?如果没有,那么实现这种签名缩小的最佳选择是什么?

谢谢!

1 个答案:

答案 0 :(得分:6)

如果仔细查看编译器错误:

 Module type declarations do not match:
         module type M_type = sig val g : int -> int val h : int -> int end
       does not match
         module type M_type = sig val g : int -> int end

您将看到编译器不会抱怨模块M,而是关于模块类型M_type

实际上,两种模块类型的定义不匹配:

module type M_type = sig
  val g : int -> int
  val h : int -> int
end

不兼容
module type M_type = sig
  val g : int -> int
end

有很多方法可以解决这个问题。 一种可能性是在不必要时不使用模块类型作为签名约束:

(* a.ml *)
module M = struct
  let g n = n + 2
  let h n = n + 3
end

同样,mli文件可以写成

(*a.mli*)    
module M : sig val g: int -> int end

另一种可能性是仅定义受约束的模块类型

(* a.ml *)
module type M_type = sig val g: int -> int end
module M: sig include M_type val h: int -> int end =
(* Note that the signature constraint above is not necessary *)
struct
  let g n = n + 2
  let h n = n + 3
end

与相关的mli文件:

(*a.mli*)
module type M_type = sig val h: int -> int end    
module M : sig val g: int -> int end

还可以为EXT文件定义扩展模块类型.ml

module type M_type = sig val g: int -> int end
module type EXT = sig include M_type val h: int -> int end
module M: EXT = struct
  let g n = n + 2
  let h n = n + 3
end
相关问题