重构2个仿函数以避免双重实现

时间:2013-09-23 22:43:14

标签: types module ocaml functor

(*我想重新提出我之前发布的一个问题,以使其更清晰并吸引更多关注......我认为问题仍然很有趣...... *)

我已经定义了一个模块类型ZONE,如下所示:

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

其中i: info用于包含各种信息,这有助于避免重复计算。它不会始终相同,因为它取决于构建Prop的{​​{1}}。例如,以下是一个仿函数,用于从Zone类型的模块构建类型为Zone的模块ZONE,其基本为PROP

info

以下是构建(* part of zone.ml *) module ZoneFun (Prop : PROP) = struct type info = { a: int } type prop = Prop.t type t = { s: string; p: prop; i: info } let f0 z = "f0" ... end 类型Zone模块的另一个仿函数,其中包含相对更复杂的ZONE

info

然后我可以按如下方式使用仿函数:

(* zoneFunPrec.ml *)
module ZoneFunPrec (Prop: PROP) (Prec: ZONESM) = struct
  type info = { a: int; b: Prec.t }
  type prop = Prop.t
  type t = { s: string; p: prop; i: info }
  let get_prec z = z.info.prec
  let f0 z = "f0"
  ...
end   

问题在于,module ZoneC = ZoneFun(PropC) module ZoneA = ZoneFunPrec(PropA)(ZonesmB) type infoget_prec有它,而ZoneFun没有)是这两个仿函数的唯一区别;他们的ZoneFunPrectype prop相同,他们的功能type tf0 ......(有很多)也完全相同。

所以我想知道如何避免两次实施f1f0等......

有没有人想要重组模块/仿函数来实现这一目标并使它们变得有意义?

2 个答案:

答案 0 :(得分:0)

很抱歉,我没有准确的代码,但您不能将常用功能粘贴在自己的module中,然后include就像:

module type ZONE =
sig
  type info
  type prop
  type t = { s: string; p: prop; i: info }
  include ZoneFunCommon
end

答案 1 :(得分:0)

创建一个仅包含共享模式的模块:

module Shared = struct
  type prop = Prop.t
  type t = { s: string; p: prop; i: info }
  let f0 z = "f0"
  ...
end

我相信你的真实f0更复杂,取决于代码中的其他内容。 (否则它可以单独在上下文之外定义。)

此模块Shared并非真正可编辑,因为它包含一些免费名称,例如Propinfo。将其更改为一个从其参数中获取这些名称的仿函数:

module MakeShared(A : sig
  module Prop : sig
    type t
  end
  type info
end) = struct
  type prop = Prop.t
  type t = { s : string; p : prop; i : info }
  let f0 z = "f0"
  ...
end

A的签名可能需要更多内容。这取决于您省略的代码。

您可以在MakeSharedZoneFun的正文中使用此ZoneFunPrec仿函数,以避免代码重复。应该是这样的:

module ZoneFun (Prop : PROP) = struct
  type info = { a: int }
  type info_ = info
  include MakeShared(struct
    module Prop = Prop
    type info = info_
  end)
end

此处需要使用类型别名info_来避免循环recusvie类型定义type info = info。与module不同,因为module Prop = Prop按预期工作,type声明始终是递归的。

这是重构代码的一种方法。可能还有其他但你的伪代码不是很清楚。例如,您可以使用MakeShared而不是在仿函数中但在创建实际实例模块的位置:

module ZoneC = struct
  include SmallerZoneFun(PropC)
  include MakeShared(...)
end