2012-11-24 11 views
5

Mam dwa moduły. Jeden definiuje typ wariantowej:Skróty nazw konstruktorów w Ocaml

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

    (* other stuff *) 
end 

i chciałbym móc używać foo „s warianty zarówno konstruktorów jak i lewostronnego dwustronnego w innym module

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 

ale za "referring to named objects" I trzeba poprzedzić nazwy wariantowe z modułem ścieżce :

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

Czy istnieje jakiś sposób, aby uniknąć u pominąć śpiewać ścieżkę modułu krótszą niż open i ciągnąc wszystkie inne rzeczy od A?

Odpowiedz

9

można otworzyć lokalnie:

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

lub

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

Można zdefiniować Bar w modułem tak, że mniej rzeczy są narażone:

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 
    ... 

Do stosowania na zewnątrz wzory, możesz zdefiniować "inteligentny konstruktor" w B:

let bar m = A.Bar m 

ETA: Zapomniałam o możliwości przekształcania definicji typu, opisaną w odpowiedzi Ashish Argwal za: type foo = A.foo = Bar of material | Baz | Boo. Biorąc pod uwagę, że w swoim przykładzie masz już skrót typu, jest to najlepsza odpowiedź.

Istnieje kilka prac na temat type-based label disambiguation, które mogą być przydatne, ale mogą nie zostać zaakceptowane w tym języku.

+0

Genialny. Dzięki. –

+1

Jeśli pracujesz "za kulisami", odwołujesz się do [propozycji ujednolicenia etykiety na podstawie typu] (http://gallium.inria.fr/~scherer/gagallium/resolving-field-names/), a następnie (1) może nie zostać zaakceptowany na końcu i (2) powinien działać dla (nie-polimorficznych) wariantów konstruktorów tak samo dobrze jak dla etykiet rekordów. – gasche

+1

Składnia 'otwórz w 'jest dostępna w OCaml od wersji 3.12 w górę. – didierc

2

Oprócz odpowiedzi udzielonych przez lukstafi, można również ponownie podać konstruktorów podczas definiowania 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

Czy jest to * bit równania * * w [3.2] (http://askra.de/software/ocaml-doc/3.12/manual016.html#toc54)? –