Types 重新构造2个函子以避免双重实现

Types 重新构造2个函子以避免双重实现,types,module,ocaml,functor,Types,Module,Ocaml,Functor,(*我想重新表述我之前发布的一个问题,以使其更清晰,吸引更多的关注…我认为这个问题仍然很有趣…*) 我定义了模块类型区域,如下所示: (* 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 module ZoneC = ZoneFun(PropC) module Zon

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

我定义了模块类型
区域
,如下所示:

(* 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
module ZoneC = ZoneFun(PropC)
module ZoneA = ZoneFunPrec(PropA)(ZonesmB)
其中
i:info
用于包含各种信息,这有助于避免重复计算。它将不总是相同的,因为它取决于构建
区域的
道具。例如,这里有一个函子,用于从类型为
PROP
的模块中构建类型为
Zone
的模块
Zone
,其中包含基本
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
(* 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   
下面是另一个用于构建类型为
Zone
的模块
Zone
,具有相对更复杂的
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
(* 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   
然后我可以按如下方式使用函子:

(* 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
module ZoneC = ZoneFun(PropC)
module ZoneA = ZoneFunPrec(PropA)(ZonesmB)
问题是,
type info
get_prec
ZoneFun
有它,而
zonefunc
没有)是这两个函子的唯一区别;它们的
类型prop
类型t
相同,它们的功能
f0
f1
。。。(有好几个)也完全一样

所以我想知道如何避免两次实现
f0
f1
,等等


有没有人想到重新构造模块/函数来实现这一点并使其具有意义?

很抱歉,我没有确切的代码给您,但是您不能将常见函数粘贴到它们自己的
模块中,然后
包括
这样:

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

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

module Shared = struct
  type prop = Prop.t
  type t = { s: string; p: prop; i: info }
  let f0 z = "f0"
  ...
end
我相信这里真正的
f0
更复杂,并且取决于代码中的其他内容。(否则,可以在上下文之外单独定义。)

此模块
Shared
实际上不可编译,因为它包含一些免费名称,如
Prop
info
。将其更改为从其参数中获取以下名称的函子:

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
的签名中可能需要更多内容。这取决于您省略的代码

您可以在
ZoneFun
zonefunc
的主体中使用此
MakeShared
functor来避免代码重复。应该是这样的:

module ZoneFun (Prop : PROP) = struct
  type info = { a: int }
  type info_ = info
  include MakeShared(struct
    module Prop = Prop
    type info = info_
  end)
end
这里需要使用类型别名
info\uu
,以避免循环递归类型定义
type info=info
。与不是递归的
module
不同,因此
module Prop=Prop
按预期工作,
type
声明始终是递归的

这是重构代码的一种方法。可能还有其他代码,但从伪代码中看不太清楚。例如,您可以在创建实际实例模块的地方,而不是在functor内部使用MakeShared:

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

请尝试尽可能小的问题,并使其可编译。您的代码包含太多对回答者来说毫无意义的细节,不完整,不可编译。分区UNPC(ProcC)是错误的。必须是ZoneFun(ProcC)您关于<代码>ZoneFun(ProcC)
的说法是正确的,刚刚修改。。。