2012-12-18 10 views
5

Mam zdefiniowane 2 moduły Zone i Zones, Zones jest lista Zone, funkcji przyczynowo z Zones trzeba zadzwonić funkcje Zone:Konstrukcja z funktorów w SML

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

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

Zasada plik all.ml wykorzystuje Zones i Mis moduły, mis.ml zawiera funkcje, które działają zarówno na Zone.t i Zones.t, na przykład val Mis.make : Zone.t -> Zones.t.

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

Teraz chciałbym mieć więcej opcji dla prop z Zone. Tak więc definiuję interfejs PROPERTY i 2 moduły, dopasowując go, aby móc tworzyć funktory dla Zone i innych, gdzie ... prop: Property.t .... Teraz mogę sobie wyobrazić kilka możliwości dla nowego 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 } 

chociaż podpisami ZonesFun i ZoneFun różnią się między 3 opcji, to realizacja może upewnić ZoneXXX.tZonesXXX.t i są spójne. Teraz jest jeden duży problem, jak zmienić Mis:

1) Jeśli zrobię funktor MisFun: PROPERTY -> MIS i zbudować ZoneXXX i ZonesXXX wewnątrz. Nie można wiedzieć, że MisXXX.Zone.t jest taki sam jak Zone.t z all.ml lub MisXXX.Zones.t jest taki sam jak Zones.t z all.ml.

2) Jeśli zrobię funktora MisFun: Zone -> Zones -> MIS, to nie mogę wiedzieć, że MisXXX.Zone.t i MisXXX.Zones.t są spójne.

Czy ktoś wie, jak rozwiązać oba 1) i 2)?

Odpowiedz

3

W opcji (1), czy stosujesz ZoneFun wewnątrz ZonesFun?

Zakładając, że myślę, że wybór jest pomiędzy (1) i (3)/(4) (które wydają się być takie same). Wybór, który należy wybrać, zależy od tego, czy musisz mieć dostęp do utworzonych modułów poza ZoneFun (potrzebujesz (4)), czy nie ((1) działa dobrze).

Aktualizacja w odpowiedzi do aktualizacji:

Jeśli dobrze rozumiem Twoje pytanie, to wydaje mi się, że Mis musi stać funktora, jak również. Ponadto, jego podpis można określić typy jak

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

gdzie X jest parametrem funktora.

(Btw, nadal nie widzę różnicy między (3) i (4), z wyjątkiem tego, że wymieniasz moduły pomocnicze.)

Aktualizacja 2:

Domyślam się, że używasz do starej i niefortunne błąd w moduł sprawdzający typu SML (patrz this discussion on the caml list). Poniższy powinien do pracy, ale nie:

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} 

można wymusić, aby pracować przez wprowadzenie typu adnotacji w MakeMisc następująco:

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 

Ale oczywiście, że nie jest bardzo przyjemne.

Jednak najpowszechniejszym sposobem wyrażenia udostępniania w ML jest, w każdym razie, fibracja, w której podajesz rodzaje lub moduły, które chcesz udostępniać abstrakcyjnie w podpisach i odpowiednio je udoskonalasz. Następnie można włączyć Zone i Zones do dodatkowych parametrów Misc funktora:

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

W wariancie (1), 'ZoneFun' stosowana jest wewnątrz' ZonesFun'. – SoftTimur

+0

Zaktualizowałem OP, jest to bardziej skomplikowane niż sądziliśmy ... – SoftTimur

+1

Zobacz moją drugą aktualizację dla szerszej odpowiedzi. –