OCaml中函子的设计

OCaml中函子的设计,ocaml,functor,Ocaml,Functor,我已经定义了两个模块区域和区域,区域是区域的列表,原因是区域的函数需要调用区域的函数: module Zone = struct type t = { ... prop: bool } ... end modules Zones = struct type t = | ZSbot | ZS of Zone.t list | ZStop ... end 原则文件all.ml使用Zones和Mis模块,Mis.ml包含在Zone.t和Zones.t上工作的函数,

我已经定义了两个模块
区域
区域
区域
区域
的列表,原因是
区域的函数
需要调用
区域
的函数:

module Zone = struct
 type t = 
 { ...
   prop: bool }
 ...
end

modules Zones = struct
  type t =
  | ZSbot
  | ZS of Zone.t list
  | ZStop
  ...
end
原则文件
all.ml
使用
Zones
Mis
模块,
Mis.ml
包含在
Zone.t
Zones.t
上工作的函数,例如
val Mis.make:Zone.t->Zones.t

open Zones
open Mis
type t = { zs: Zones.t }
...
Mis.make z
现在,我想为
区域
道具
提供更多选项。因此,我定义了一个接口
属性
和两个与之匹配的模块
类型
公式
,这样我就可以为
区域
和其他
区域生成函数。。。prop:Property.t…
。现在我可以想象新的
all.ml
有几种可能性:

(* 1 *)
open Zones
module ZonesType = ZonesFun(Type)
module ZonesFormula = ZonesFun(Formula)
type t = { zstype: ZonesType.t; zsformula: ZonesFormula }

(* 3 *)
open Zones
module ZonesType = ZonesFun(ZoneFun(Type))
module ZonesFormula = ZonesFun(ZoneFun(Formula))
type t = { zstype: ZonesType.t; zsformula: ZonesFormula }

(* 4 *)
open Zones
module ZoneType = ZoneFun(Type)
module ZoneFormula = ZoneFun(Formula)
module ZonesType = ZonesFun(ZoneType)
module ZonesFormula = ZonesFun(ZoneFormula)
type t = { zstype: ZonesType.t; zsformula: ZonesFormula }
虽然三个选项中的
ZonesFun
ZoneFun
的签名不同,但此实现可以确保
ZoneXXX.t
ZonesXXX.t
是一致的。现在一个大问题是如何改变Mis:

1) 如果我制作一个函子
MisFun:PROPERTY->MIS
,并在里面构建
ZoneXXX
ZoneXXX
。它无法知道
MisXXX.Zone.t
all.ml的
Zone.t
相同,或者
MisXXX.Zones.t
all.ml的
Zones.t
相同

2) 如果我使一个函子
MisFun:Zone->Zones->MIS
,它就不能知道
MisXXX.Zone.t
MisXXX.Zones.t
是一致的

有人知道如何解决1)和2)吗?

在选项(1)中,您是否在
ZoneFun
中应用
ZoneFun

假设是这样,我认为选择是在(1)和(3)/(4)之间(看起来是一样的)。选择哪一个取决于您是否需要能够访问在
ZoneFun
之外创建的
Zone
模块(您需要(4))((1)工作正常)

更新以回复更新:

如果我正确理解了你的问题,那么在我看来,
Mis
也必须成为函子。此外,它的签名可以指定以下类型

val make: ZoneFun(X).t -> ZonesFun(X).t
其中
X
是函子参数

(顺便说一句,我仍然看不出(3)和(4)之间有什么区别,只是您命名了辅助模块。)

更新2:

我猜您在OCaml的模块类型检查器中遇到了一个旧的、不幸的错误(请参阅)。以下内容应该有效,但不能:

module type PROP = sig type t end
module type ZONE = sig type t end
module MakeZone (P : PROP) = struct type t = {p : P.t} end
module MakeZones (Z : ZONE) = struct type t = ZS of Z.t list end

module MakeMisc (P : PROP) :
sig
  val make : MakeZone(P).t -> MakeZones(MakeZone(P)).t
end =
struct
  module Zone = MakeZone(P)
  module Zones = MakeZones(Zone)
  let make z = Zones.ZS [z]
end

module Type = struct type t = T end
module Formula = struct type t = F end
module ZoneType = MakeZone(Type)
module ZoneFormula = MakeZone(Formula)
module ZonesType = MakeZones(ZoneType)
module ZonesFormula = MakeZones(ZoneFormula)
module MiscType = MakeMisc(Type)
module MiscFormula = MakeMisc(Formula)
let zst = MiscType.make {ZoneType.p = Type.T}
let zsf = MiscFormula.make {ZoneFormula.p = Formula.F}
通过在
MakeMisc
中输入类型注释,可以强制使其工作,如下所示:

module MakeMisc (P : PROP) :
sig
  val make : MakeZone(P).t -> MakeZones(MakeZone(P)).t
end =
struct
  module Zone : sig type t = MakeZone(P).t end = MakeZone(P)
  module Zones :
    sig type t = MakeZones(MakeZone(P)).t = ZS of MakeZone(P).t list end =
    MakeZones(MakeZone(P))
  let make z = Zones.ZS [z]
end
但很明显,这不是很愉快

然而,在ML中表示共享的常用方法是fibritation,即在签名中抽象地命名要共享的类型或模块,并相应地细化它们。然后,您可以将
区域
区域
转换为
Misc
functor的附加参数:

module type PROP = sig type t end
module type ZONE = sig type prop type t = {p : prop} end
module type ZONES = sig type zone type t = ZS of zone list end
module MakeZone (P : PROP) = struct type prop = P.t type t = {p : prop} end
module MakeZones (Z : ZONE) = struct type zone = Z.t type t = ZS of zone list end

module MakeMisc
  (P : PROP) (Z : ZONE with type prop = P.t) (Zs : ZONES with type zone = Z.t) :
sig
  val make : Z.t -> Zs.t
end =
struct
  let make z = Zs.ZS [z]
end

module Type = struct type t = T end
module Formula = struct type t = F end
module ZoneType = MakeZone(Type)
module ZoneFormula = MakeZone(Formula)
module ZonesType = MakeZones(ZoneType)
module ZonesFormula = MakeZones(ZoneFormula)
module MiscType = MakeMisc(Type)(ZoneType)(ZonesType)
module MiscFormula = MakeMisc(Formula)(ZoneFormula)(ZonesFormula)
let zst = MiscType.make {ZoneType.p = Type.T}
let zsf = MiscFormula.make {ZoneFormula.p = Formula.F}
在选项(1)中,
ZoneFun
应用于
ZonesFun
中。