2013-03-10 3 views
9

Desidero essere in grado di definire un tipo (ad esempio my_type) che possa identificare le hashtable con stringhe come chiavi e mappato a valori interi.
Così, ho provatoIdentificazione di hash come tipo definito dall'utente in OCaml

# type my_type = (string, int) Hashtbl.t;; 

Ma, quando provo

# let a = Hashtbl.create 100;; 
val a : ('_a, '_b) Hashtbl.t = <abstr> 
# Hashtbl.add a "A" 12;; 
- : unit =() 
# a;; 
- : (string, int) Hashtbl.t = <abstr> 

Gli spettacoli ultima linea (string, int) Hashtbl.t = sommario invece di my_type. Come posso assicurarmi che mi dia il tipo di hashtable come my_type?

risposta

1

my_type è solo un sinonimo di (string, int) Hashtbl.t, è possibile utilizzare entrambi in modo intercambiabile.

Si può dire al compilatore che a è di tipo my_type, e ottenere l'output più bello, in questo modo:

# let (a:my_type) = Hashtbl.create 100;; 
val a : my_type = <abstr> 
# a;; 
- : my_type = <abstr> 

Se vi state chiedendo su <abstr>, significa che il livello superiore non sa come stampa a (il suo contenuto, non il suo tipo).

2

Aggiornamento: mi dispiace, come Gasche sottolinea, è possibile utilizzare un tipo semplice annotazione per farlo, dimenticare il tipo di coercizione

# type my_type = (string, int) Hashtbl.t;; 
type my_type = (string, int) Hashtbl.t 
# let (a : my_type) = Hashtbl.create 100;; 
val a : my_type = <abstr> 
+1

Questo non è un ottimo suggerimento: non si tratta di sottotitolare qui, ma semplicemente di due tipi uguali. La coercizione non ha molto senso, come farebbe un'annotazione di tipo semplice, e in effetti anche un'annotazione di tipo è di scarsa utilità. – gasche

+0

Hai ragione, ho dimenticato l'annotazione del tipo .. Questo non è davvero un buon consiglio .. – octref

9

Non ha senso dichiarare Sinonimi di tipo e di aspettarsi al compilatore di usa una delle due espressioni in situazioni precise: dato che sono di uguali tipi, il compilatore userà una delle due e su di essa avrai un minimo controllo.

Se si desidera applicare tipo di astrazione, in modo da non mescolare un tipo my_type con qualsiasi altro (string, int) Hashtbl.t, si dovrebbe definire un nuovo tipo con una marcatura la differenza costruttore:

type my_type = Tbl of (string, int) Hashtbl.t 
let a = Tbl (Hashtbl.create 100) 
let add (Tbl t) k v = Hashtbl.add t k v 

si consiglia questo (e paghi il costo di dover trasformare tutti i valori di my_type in hashtables con pattern matching specifico quando si desidera utilizzare una delle funzioni Hashtbl, oppure si può voler manipolare solo un sinonimo di tipo, ma in quest'ultimo caso non si dovrebbe si aspetta che l'output del compilatore riporti qualsiasi tipo particolare.

+1

A partire da OCaml 3.11 puoi usare "abbreviazioni di tipo privato" per ottenere un nuovo tipo senza sovraccarico di runtime (non l'ho mai controllato personalmente). Per questo si usa 'type my_type = private (string, int) Hashtbl.t'. All'interno del modulo di definizione 'my_type' è solo un'abbreviazione di tipo semplice. Al di fuori, tuttavia, sono necessarie funzioni di conversione esplicite. Per una direzione anche le coercizioni funzionano, ad esempio, 't:> (stringa, int) Hashtbl.t' per forzare' t' di tipo 'my_type' in una tabella hash. – chris

+0

@chris: Ma supponiamo un'astrazione del modulo, al di fuori della quale hai solo un lato della conversione. Ciò che sarebbe necessario qui è una "abbreviazione di tipo opaco" che consente * entrambe le direzioni di conversione ma le impone di essere esplicite, come fa "privato" rispetto ai sinonimi usuali. – gasche