隐藏在OCaml中的外部和内部接口和信息
问题描述:
从多个模块创建库时,我无法找到一种很好的方法,可以在访问所需的所有内容的同时对库(外部接口)的用户执行正确的信息隐藏内部接口。隐藏在OCaml中的外部和内部接口和信息
更具体地说,我有两个模块(文件a.ml [i]和b.ml [i])。在A中,我定义了一些类型t,这是我不想从用户(外部接口)隐藏的内部结构。
module A : sig
type t
end
module A = struct
type t = float
end
在模块B,然后我想用秘密型A.t
。
module B : sig
create_a : float -> A.t
end
module B = struct
create_a x = x
end
当然这并不编译,因为B的编译单元不知道的A.t
类型。
解决方案,我知道,但不喜欢:
- 移动功能
create_a
到模块A
- 复制的
A.t
的定义B
,并与一些external cheat : `a -> `b = "%identity"
有没有其他方法可以知道B
中A.t
的类型,而不会将此信息泄露到库的界面?
答
一如往常,间接的额外层可以解决这个问题。定义一个模块Lib
,将指定一个外部接口,例如,
module Lib : sig
module A : sig
type t
(* public interface *)
end
module B : sig
type t
(* public interface *)
end = struct
module A = A
module B = B
end
如果你不想重复自己,写模块签名的两倍,那么你就可以一次一个模块sigs.ml
中定义它们:
module Sigs = struct
module type A = sig
type t
(* public interface *)
end
(* alternatively, you can move it into sigs_priv.ml *)
module type A_private = sig
include A
val create_a : float -> t
end
...
end
最后,请确保在安装步骤中未安装接口(.cmi
文件), ,以便用户无法绕过抽象。如果你使用的是绿洲,那么很简单:只要让你的所有模块都在内部,除了模块Lib
,即用InternalModules
字段指定它们。
不错!再见'包'选项。 – lambdapower