从多个模块创建库时,我找不到一种很好的方法来对库的用户(外部接口(interface))进行适当的信息隐藏,同时能够在内部接口(interface)上访问我需要的所有内容。
更具体地说,我有两个模块(文件 a.ml[i] 和 b.ml[i])。在 A 中,我定义了一些类型 t,这是我不想对用户隐藏的内部结构(外部接口(interface))。
module A : sig
type t
end
module A = struct
type t = float
end
然后在模块 B 中,我想使用
A.t
的 secret 类型.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"
欺骗类型检查器有没有其他方法可以知道
A.t
的类型?在 B
没有将此信息泄漏到图书馆的界面?
最佳答案
与往常一样,额外的间接层可以解决这个问题。定义一个模块Lib
这将指定一个外部接口(interface),例如,
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
最后,确保您没有安装接口(interface)(
.cmi
文件),在您的安装步骤中,以便用户无法绕过您的抽象。如果您使用的是 oasis,那么这很简单:只需将所有模块设置为内部,模块
Lib
除外。 ,即用 InternalModules
指定它们 field 。
关于module - 隐藏在 OCaml 中的外部和内部接口(interface)和信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40970844/