使用类型别名扩展模块

时间:2013-03-07 11:52:02

标签: ocaml

我正在尝试使用ocaml-inotify包。该问题的相关部分可以定义如下

module Inotify : sig
  type wd
  val int_of_wd : wd -> int
end = struct
  type wd = int
  let int_of_wd wd = wd
end

这项工作是在一个setuid脚本中进行的,我希望inotify部分处理得没有特权,所以我要分配,然后安排到孩子的非特权用户。但是,这意味着我需要通过管道将wd实体传递回父级,因此需要序列化和反序列化它们,需要int_to_wd函数。

我尝试按如下方式扩展模块:

module Rich_Inotify : sig 
  include module type of Inotify with type wd := int
  val wd_of_int : int -> wd
end = struct
  include Inotify
  let wd_of_int (wd:int) : wd = wd 
end
module Inotify = Rich_Inotify

但是,编译器抱怨wdint而不是wd。我如何说服这些类型相同?

1 个答案:

答案 0 :(得分:4)

如果Inotify模块确实是用这个签名定义的,那么用抽象类型密封,你就无法打破它的抽象,把它重新定义为int。我的意思是你的签名(module type of Foo with wd := int)很聪明,并描述了你想要的界面,但实现Foo 满足它:如果类型检查器允许,那么就会有根本没有类型抽象。

您应该请求ocaml-inotify维护者添加编组基元(如果需要,可以在本地分叉)。他或她可以向wd = int发布转换函数(以便将来的实现更改仍然可以实现这些函数),或者直接来往于int,而不是公开string的事实。如果你只对编组感兴趣并希望公开更少的内部细节。

有一个解决方案可以公开更多内部细节,即来回转换为抽象类型,即使用private type abbreviations

sig
  type t = private int
  val mk : int -> t
end

此签名公开内部表示为int,并允许使用tint明确地从(foo :> int)投射到(foo : t :> int)(您知道这是运行时的无操作),但是不允许反向转换,所以你不得不使用mk函数,我认为它将进行某种范围检查以确保这是一个有效的描述符。

(有些人可能会建议,作为一种解决方法,您可以通过使用不应该命名的不安全的强制转换来破坏语言的类型安全性。不要;这是不好的建议。)