2011-12-15 18 views
11

Quando si utilizza l'interprete interattivo GHC, è possibile richiedere il tipo derivato di un'espressione:In che modo GHCi seleziona i nomi per le variabili di tipo?

Prelude> :t map 
map :: (a -> b) -> [a] -> [b] 

Sembra che ci vogliono i nomi delle variabili di tipo dalla firma dal map è defined come

map :: (a -> b) -> [a] -> [b] 
map _ []  = [] 
map f (x:xs) = f x : map f xs 

nel Preludio. Questo ha molto senso! La mia domanda è: come vengono scelti i nomi delle variabili di tipo quando non è stata data la firma?

Un esempio potrebbe essere

Prelude> :t map fst 
map fst :: [(b, b1)] -> [b] 

dove raccolse i nomi b e b1. E 'chiaro che la ridenominazione deve avvenire, ma semplicemente a cominciare a, b, ... avrebbe dato

map fst :: [(a, b)] -> [a] 

invece, che trovo un po' più leggibile.

risposta

13

Come ho capito, ghci sceglie i nomi nello stesso ordine in cui deduce i tipi. Utilizza lo schema di denominazione come indicato per decidere il nome del tipo del risultato, che è [b] perché quello è il nome del tipo specificato nella definizione di map. Quindi decide che la funzione che è il primo parametro per map deve restituire anche qualcosa di tipo b.

Il tipo di variabile rimanente di essere nominato è quindi la variabile di tipo per il secondo elemento nella tupla argomento per fst, e ancora una volta, si guarda alla definizione di fst per decidere quale nome da utilizzare. La definizione di fst :: (a, b) -> a, quindi b sarebbe il nome preferito qui, ma dal momento che lo b è già in uso, viene aggiunto uno 1 in modo che diventi b1.

Penso che questo sistema abbia vantaggi in situazioni in cui non si affrontano tipi arbitrari come nel caso qui. Se il tipo risultante è qualcosa di simile, per esempio:

castAdd :: (Num n, Num n1, Num n2) => n -> n1 -> n2 

... è probabilmente più leggibile di:

castAdd :: (Num a, Num b, Num c) => a -> b -> c 

... perché si può in gran parte affidamento su che n# significa un numerica digitare, poiché la definizione di classe per Num è class Num n where ....

MODIFICA: Sì, so che è impossibile implementare castAdd, ma è solo un esempio di tipo.

+1

Grazie, questa è una bella spiegazione! Non avevo pensato al caso in cui si desidera che diversi 'n' vengano rinominati ma rimangano correlati. –

+0

Non è impossibile. (unSafeCoerce o semplicemente vecchio '_ | _') – PyRulez