OCaml中的仿函数设计

Sof*_*mur 5 ocaml functor

我已经定义了2个模块ZoneZones,Zones是名单Zone中的原因的功能,Zones需要调用的函数Zone:

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

modules Zones = struct
  type t =
  | ZSbot
  | ZS of Zone.t list
  | ZStop
  ...
end
Run Code Online (Sandbox Code Playgroud)

一个原则文件all.ml使用ZonesMis模块, mis.ml包含在两个工作职能Zone.tZones.t,例如val Mis.make : Zone.t -> Zones.t.

open Zones
open Mis
type t = { zs: Zones.t }
...
Mis.make z
Run Code Online (Sandbox Code Playgroud)

现在,我想有更多的选择propZone.所以我定义了一个接口PROPERTY和2个模块TypeFormula匹配它,这样我就可以为Zone其他人制作仿函数... 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 }
Run Code Online (Sandbox Code Playgroud)

虽然3个选项的签名ZonesFun和签名ZoneFun不同,但这种实现可以确保ZoneXXX.t并且ZonesXXX.t是连贯的.现在一个大问题是如何改变Mis:

1)如果我做一个仿函数MisFun: PROPERTY -> MIS,并构建ZoneXXXZonesXXX内部.它不能知道MisXXX.Zone.t是相同Zone.tall.ml,还是MisXXX.Zones.t相同Zones.tall.ml.

2)如果我制作一个仿函数MisFun: Zone -> Zones -> MIS,它就无法知道MisXXX.Zone.t并且MisXXX.Zones.t是连贯的.

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

And*_*erg 3

在选项(1)中,您是ZoneFun在内部申请吗ZonesFun

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

更新回复更新:

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

val make: ZoneFun(X).t -> ZonesFun(X).t
Run Code Online (Sandbox Code Playgroud)

其中X是函子参数。

(顺便说一句,除了您命名辅助模块之外,我仍然认为(3)和(4)之间没有区别。)

更新2:

我的猜测是,您在 OCaml 的模块类型检查器中遇到了一个古老且不幸的错误(请参阅caml 列表上的讨论)。以下内容应该有效,但无效:

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}
Run Code Online (Sandbox Code Playgroud)

您可以通过添加类型注释来强制使其工作,如下所示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
Run Code Online (Sandbox Code Playgroud)

但显然,这不太令人愉快。

然而,无论如何,在 ML 中表达共享的常见方法是通过fibration,您可以在签名中抽象地命名要共享的类型或模块,并相应地对其进行细化。然后您可以将Zone和转换Zones为函子的附加参数Misc

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}
Run Code Online (Sandbox Code Playgroud)