模块签名中的类实例类型强制

时间:2011-01-10 12:58:18

标签: module ocaml signature coercion

我的一些模块包含全局类实例,这些实例使用两个方法private_methodpublic_method实现给定的类类型。

我希望MyModule.my_instance # public_method可以在我的计划中的任何位置使用,MyModule.my_instance # private_method仅在MyModule内可用。

我尝试过以下方法:

class type public_type = object
  method public_method  : int
end ;;

class type private_type = object
  method public_method  : int
  method private_method : int
end ;;

let make_private : unit -> private_type = fun () -> object
  method public_method  = 0
  method private_method = 0
end ;;

module type MY_MODULE = sig
  val my_instance : public_type
end

module MyModule : MY_MODULE = struct
  let my_instance = make_private ()
  let _           = print_int (my_instance # private_method)
end 

但是,这会导致错误:

  

值不匹配:

     

val my_instance : private_type

     

未包含在

中      

val my_instance : public_type

可以手动编写强制:

module MyModule : MY_MODULE = struct
  let my_instance = make_private ()
  let _           = print_int (my_instance # private_method)

  let my_instance = (my_instance :> public_type)
end 

但是我不想为这么简单的东西加倍代码大小。

您对此为何会有什么建议,以及如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

ocaml中没有隐含的强制。也许值得将强制放入仿函数(如果你有几个具有相同属性的模块):

module Hide(M:sig val my_instance : private_type end) : MY_MODULE =
struct
  let my_instance = (M.my_instance :> public_type)
end

module MyModule = Hide (struct
  let my_instance = make_private ()
  let _           = print_int (my_instance # private_method)
end)

答案 1 :(得分:3)

解决此问题的最佳技巧可能是使用Garrigue所描述的private row types(“私人行类型:抽象未命名”;请查阅,因为我无法发布第二个链接)。这可以与显式对象类型表达式一起使用:

module type MY_MODULE2 = sig
  type t = private < public_method : int; ..>
  val my_instance : t
end ;;

module MyModule2 : MY_MODULE2 = struct
  type t = private_type
  let my_instance = make_private ()
  let _           = print_int (my_instance # private_method)
end  ;;

或使用对象路径(这是您需要的):

module type MY_MODULE3 = sig
  type t = private #public_type
  val my_instance : t
end ;;

module MyModule3 : MY_MODULE3 = struct
  type t = private_type
  let my_instance = make_private ()
  let _           = print_int (my_instance # private_method)
end  ;;