Module 从2个函子中提取公共函数

Module 从2个函子中提取公共函数,module,ocaml,functor,Module,Ocaml,Functor,我已经定义了一个模块类型ZONE和两个functor(ZoneFun和zonefunc)来构建它: (* zone.ml *) module type ZONE = sig type info type prop type t = { p: prop; i: info } val f1 : t -> string end module ZoneFun (Prop : PROP) = struct type info = { a: int } type prop =

我已经定义了一个模块类型
ZONE
和两个functor(
ZoneFun
zonefunc
)来构建它:

(* zone.ml *)
module type ZONE =
sig
  type info
  type prop
  type t = { p: prop; i: info }
  val f1 : t -> string
end

module ZoneFun (Prop : PROP) = struct
  type info = { a: int }
  type prop = Prop.t
  type t = { p: prop; i: info }
  let f1 z = "f1"
end

(* zoneFunPrec.ml *)
module ZoneFunPrec (Prop: PROP) (Prec: ZONESM) = struct
  type info = { a: int; b: Prec.t }
  type prop = Prop.t
  type t = { p: prop; i: info }
  let f1 z = "f1"
  let get_prec z = z.info.prec
end   
这两个函子中的某些函数的实现方式不同(例如,
f0
);有些功能完全相同(例如
f1
)。我的问题是如何提取这些常用函数以避免重复实现它们

编辑:(我意识到我需要提供更具体的信息,以使其更清晰…很抱歉更改…)

ZoneFun
zonefunc
之间存在一些差异:

1) 它们的
类型信息
不相同 2)
zonefunc
get_prec
ZoneFun
没有,并且
ZONE
的签名不需要它


因此,稍后我可以编写
模块ZoneB=ZoneFun(B)
模块ZoneA=zonefunc(C)(ZonesmD)
来构建分区…

您可以执行以下操作:

module ZoneFunPrec (Prop: PROP) = struct
  module Zone1 = ZoneFun(Prop)
  type prop = Prop.t
  type t = string
  let f0 x = "f0 in ZoneFunPrec"
  let f1 = Zone1.f1
end
但是,只有在不将签名归于函子的情况下,这才有效

module ZoneFunPrec (Prop: PROP) : ZONE = ...
如果你想要不透明的归属,你可以这样做

(* No ascription here *)
module SharedFn (Prop : PROP) = struct
  type prop = Prop.t
  type t = string
  let f0 x = "f0 in ZoneFun"
  let f1 x = "f1"
end

(* Ascribe the module to hide the types *)  
module ZoneFun (Prop : PROP) : ZONE = struct
  module Shared = SharedFn(Prop)
  let f1 = Shared.f1
  ...defs specific to ZONE...
end 

module ZoneFunPrec (Prop: PROP) : ZONE_PREC = struct
  module Shared = SharedFn(Prop)
  type prop = Prop.t
  type t = string
  let f0 x = "f0 in ZoneFunPrec"
  let f1 = Shared.f1
  ...defs specific to ZONE_PREC...
end

您可以尝试使用
include Shared
来保存类型,但是类型是抽象的,因此不太灵活。

就像重构代码的最佳实践一样?或者你在寻找一个自动化的或者包含反射的答案?重新分解代码的解决方案是可以的,但是这两个函子有很多相同的函数,我只想写一次就行了……如果你创建了一个具有通用函数的模块,那么1)使用“包含”在每个模块中导出它2)在两个模块中“打开”模块。这取决于这些函数子集的使用方式。问题是这些函数需要
Zone.t
(例如
f1
),因此如果我添加另一个模块,我不太确定编译的顺序……谢谢您的评论,但是
zonefunc
的签名与
ZoneFun
不同,这使事情变得复杂…在我可以使用
module ZoneA=zonefunc(A)(ZonesmB)
构建模块
ZoneA
之前,但如果您的建议被采纳,我不知道这段代码会是什么样子。。。请您为ZONE_PREC的零件
…DEF写多一点好吗?我只是更改了一点OP以使其更清楚,很抱歉。。。我认为我们已经接近解决方案了。。。