2012-12-18 4 views
5

ho definito 2 moduli Zone e Zones, Zones è una lista di Zone, delle funzioni Causa di Zones bisogno di richiamare le funzioni di Zone:Un disegno di funtori in OCaml

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

modules Zones = struct 
    type t = 
    | ZSbot 
    | ZS of Zone.t list 
    | ZStop 
    ... 
end 

Un principio di file all.ml utilizza Zones e i moduli Mis, mis.ml contengono funzioni che funzionano su entrambi Zone.t e Zones.t, ad esempio val Mis.make : Zone.t -> Zones.t.

open Zones 
open Mis 
type t = { zs: Zones.t } 
... 
Mis.make z 

Ora, vorrei avere più opzioni per la prop di Zone. Quindi definisco un'interfaccia PROPERTY e 2 moduli Type e Formula corrispondenti, in modo da poter rendere functors per Zone e altri dove ... prop: Property.t .... Ora posso immaginare diverse possibilità per il nuovo 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 } 

Anche se le firme di ZonesFun e ZoneFun sono diversi tra le 3 opzioni, questa implementazione può assicurarsi ZoneXXX.t e ZonesXXX.t sono coerente. Ora un grande problema è come cambiare Mis:

1) Se faccio un funtore MisFun: PROPERTY -> MIS, e crea il ZoneXXX e ZonesXXX all'interno. Non può sapere che MisXXX.Zone.t è uguale a Zone.t di all.ml o MisXXX.Zones.t corrisponde a Zones.t di all.ml.

2) Se eseguo un functor MisFun: Zone -> Zones -> MIS, non è possibile sapere che MisXXX.Zone.t e MisXXX.Zones.t sono coerenti.

Qualcuno sa come risolvere entrambi 1) e 2)?

risposta

3

Nell'opzione (1), si applica ZoneFun all'interno di ZonesFun?

Supponendo che, penso che la scelta sia tra (1) e (3)/(4) (che sembrano essere gli stessi). Quale scegliere dipende dal fatto che sia necessario accedere ai modulicreati all'esterno di ZoneFun (necessario (4)) o meno ((1) funziona correttamente).

Aggiornamento in risposta per aggiornare:

Se ho capito bene la tua domanda, allora mi sembra che Mis deve diventare un funtore pure. Inoltre, la sua firma può specificare i tipi come

val make: ZoneFun(X).t -> ZonesFun(X).t 

dove X è il parametro funtore.

(Btw, non vedo ancora alcuna differenza tra (3) e (4), tranne che si nominano i moduli ausiliari.)

Aggiornamento 2:

La mia ipotesi è che si esegue in un vecchio e sfortunato bug nel tipo di modulo correttore di OCaml (vedi this discussion on the caml list). Il seguente dovrebbe lavoro, ma non lo fa:

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} 

È possibile forzare per farla funzionare mettendo in annotazioni di tipo in MakeMisc come segue:

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 

Ma, ovviamente, che non è molto piacevole.

Tuttavia, il modo comune di esprimere condivisione in ML, in ogni caso, è da fibrazione, dove è il nome del tipo o moduli che si vogliono condividere con astrattamente nelle firme e perfezionare di conseguenza. Poi si può girare Zone e Zones in parametri addizionali del Misc funtore:

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} 
+0

In opzione (1), 'ZoneFun' viene applicata all'interno' ZonesFun'. – SoftTimur

+0

Ho aggiornato l'OP, è più complicato di quello che pensavamo ... – SoftTimur

+1

Vedere il mio secondo aggiornamento per una risposta più ampia. –