2016-12-05 70 views
2

从多个模块创建库时,我无法找到一种很好的方法,可以在访问所需的所有内容的同时对库(外部接口)的用户执行正确的信息隐藏内部接口。隐藏在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类型。

解决方案,我知道,但不喜欢:

  1. 移动功能create_a到模块A
  2. 复制的A.t的定义B,并与一些external cheat : `a -> `b = "%identity"
欺骗类型检查

有没有其他方法可以知道BA.t的类型,而不会将此信息泄露到库的界面?

回答

3

一如往常,间接的额外层可以解决这个问题。定义一个模块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字段指定它们。

+0

不错!再见'包'选项。 – lambdapower