2014-05-11 16 views
5

cerco di utilizzare i tipi parametrici in OCaml ma doesnt't lavoro :(tipi parametrizzati in OCaml

In un primo file "tree.ml" Io definisco il tipo:

type 'a tree = 
    | Node of ('a tree)*('a tree) 
    | Leaf of 'a 

In un altro file "intTree.ml", io uso questo tipo per definire un tipo di t:

open Tree 
type t = int tree 

Infine, voglio utilizzare il tipo t in una funzione "formato" in "main.ml":

open IntTree 

type r = IntTree.t 

let rec size tree = match tree with 
    | Leaf k -> 0 
    | Node (t1,t2) -> 1 + size t1 + size t2 

Quando provo a compilare questi file, ottengo il seguente errore:

File "main.ml", line 6, characters 4-8: 
Error: Unbound constructor Leaf 

Se ho definito "main.mli", non cambia nulla:

type r 

val size : r -> int 

Se ho messo:

let rec size (tree : r) = match tree with 
    | Leaf k -> 0 
    | Node (t1,t2) -> 1 + size t1 + size t2 

ho:

So che sono soluzioni per risolvere rapidamente questo errore (ad esempio, mettendo "open Tree type t = int tree" in main.ml invece di "open IntTree type t = IntTree.t") ma ho bisogno di usa la struttura precedente (per altri motivi ...). C'è una soluzione?

Grazie

+0

Il tuo 'main.ml' apre' IntTree', quindi ottiene tutti i nomi definiti lì. Tuttavia, 'Leaf' non è definito lì; è definito in 'Tree'. Quindi, come dice Kadaku, dovresti aprire 'Tree' nel tuo' main.ml'. Sembra un sacco di problemi, ma è perché i tuoi moduli sono così piccoli.In un progetto reale avresti più nomi da controllare. –

+2

Inoltre, invece di aprire, ho trovato personalmente più utile in un grande progetto utilizzare il nome completo, 'Tree.Leaf'. – nlucaroni

risposta

5

È necessario open Tree in main.ml. Non è necessario copiare e incollare la dichiarazione del tipo. In te il compilatore del codice prova a indovinare cosa ti passa per la mente. Ecco perché aggiungere annotazioni di tipo manualmente risolve parzialmente il problema.

compilatore vede che ci si aspetta tree essere di tipo r, esamina tipo r dal modulo IntTree (che si apre con voi) e lì si capisce che probabilmente abbiamo questa costruttori nel modulo Tree. Lo apre con un avvertimento. Questa funzione è stata introdotta piuttosto recentemente, quindi non essere sorpreso di non esserne a conoscenza.

4

Un'altra soluzione è quella di cambiare questo:

open Tree 

a questo:

include Tree 

in intTree.ml. L'idea è che intTree diventa autonomo includendo tutte le definizioni da Tree.

0

Mentre l'aggiunta open Tree in "main.ml" risolverà il problema, potrebbe essere preferibile scrivere il seguente di non inquinare "main.ml" con eventuali definizioni irrilevanti di "Tree.mli":

let rec size tree = match tree with 
    | Tree.Leaf k -> 0 
    | Tree.Node (t1,t2) -> 1 + size t1 + size t2