2012-11-24 12 views
5

Ho due moduli. Si definisce un tipo variante:Nomi di costruttori abbreviati in Ocaml

module A = struct 
    type foo = Bar of material | Baz | Boo 

    (* other stuff *) 
end 

e vorrebbe poter utilizzare foo 's varianti sia come costruttori e come sinistra-lati in un altro modulo

module B = struct 
    type foo = A.foo (* I can abbreviate A.foo by assigning it a local alias *) 

    let f (x : foo) = match x with 
    | Bar m  -> Bar (g m) (* Any way to abbreviate Bar and friends? *) 
    | Baz | Boo -> x 
end 

ma per "referring to named objects" I deve prefissare nomi variante con un modulo percorso:

let f (x : foo) = match x with 
    | A.Bar m   -> A.Bar (g m) 
    | A.Baz | A.Boo -> x 

c'è un modo per saltare evitare u cantare il percorso del modulo a corto di open e inserire tutte le altre cose da A?

risposta

9

è possibile aprire un locale:

let f (x : foo) = A.(match x with 
    | Bar m  -> Bar (g m) 
    | Baz | Boo -> x) 

o

let f (x : foo) = 
    let open A in 
    match x with 
    | Bar m  -> Bar (g m) 
    | Baz | Boo -> x) 

È possibile definire Bar in un modulo in modo che meno cose sono esposte:

module A = struct 
    module BasicDataAndOps = struct 
    type foo = Bar of material | Baz | Boo 
    end 
    open BasicDataAndOps 
    (* other stuff *) 
end 

module B = struct 
    open A.BasicDataAndOps 
    ... 

Per l'uso al di fuori di modelli, è possibile definire un "costruttore intelligente" in B:

let bar m = A.Bar m 

ETA: Ho dimenticato la possibilità di rideterminare la definizione del tipo, descritta nella risposta di Ashish Argwal: type foo = A.foo = Bar of material | Baz | Boo. Dato che hai già l'abbreviazione di tipo nel tuo esempio, questa è la migliore risposta.

C'è del lavoro su type-based label disambiguation che potrebbe essere utile, ma potrebbe non essere accettato nella lingua.

+0

Brillante. Grazie. –

+1

Se con il lavoro "dietro le quinte" ci si riferisce alla [proposta di disambiguazione dell'etichetta basata sui tipi] (http://gallium.inria.fr/~scherer/gagallium/resolving-field-names/), quindi (1) potrebbe non essere accettato alla fine e (2) dovrebbe funzionare per costruttori di varianti (non polimorfici) così come per le etichette discografiche. – gasche

+1

la sintassi 'open in' è disponibile in OCaml dalla versione 3.12 in poi. – didierc

2

Oltre alle risposte fornite da lukstafi, è anche possibile ripetere i costruttori durante la definizione di B.foo.

module A = struct 
    type foo = Bar | Baz 
end 

module B = struct 
    type foo = A.foo = Bar | Baz 

let f (x : foo) = match x with 
    | Bar -> "bar" 
    | Baz -> "baz" 

end 
+0

È questo il bit * di equazione del tipo * in [3.2] (http://askra.de/software/ocaml-doc/3.12/manual016.html#toc54)? –