2014-07-25 13 views
6

Sto leggendo su valutazioni pigre in haskell e ho una domanda. Per esempio abbiamo seguenti calcoli:Valutazioni pigre delle strutture dati

Prelude> let x = 1 + 1 :: Int 
Prelude> let y = (x,x) 

E dopo aver ottenuto il valore di x:

Prelude> :sprint x 
x = _ 

E 'non valutata. Ok, ora veniamo valore di y:

Prelude> :sprint y 
y = (_,_) 

E 'non valutata troppo, perché y dipende x and it's unevaluated. Ora proviamo lo stesso esempio, ma senza ::Int:

Prelude> let x = 1 + 1 
Prelude> let y = (x, x) 
Prelude> :sprint y 
y = _ 

Perché y valore è _ invece (_, _) quando stiamo cercando senza ::Int?

vedo che hanno diversi tipi:

Prelude> let x = 1 + 1 
Prelude> :t x 
x :: Num a => a 
Prelude> let x = 1 + 1 :: Int 
Prelude> :t x 
x :: Int 

Ma perché i valori di y dipende da esso?

Grazie.

+1

Ora per la parte davvero divertente, con 'x' che ha tipo' Num a => a', cosa succede dopo aver valutato completamente sia 'x' che' y'? Cosa succede alla loro rappresentazione ': sprint'? – bheklilr

+0

@bheklilr, sì, molto interessante. Ho fatto: 'seq' per' x' e 'y', essi stampano valori, ma: stampe sprint' _' – 0xAX

+1

Che cosa significa anche "valutare" 'x' quando il suo tipo è' Num a => a' ? Come fa il compilatore a sapere cosa fare con esso? Come è in grado di dire che il valore di 'x' è' 2' quando non sa quale implementazione di '+' usare? Potrei implementare il mio newtype attorno a 'Int' che ha' + 'definito come' (MyInt x) + (MyInt y) = MyInt (x - y) ', quindi cosa sta facendo GHC qui per poter stampare quel' x 'ha valore' 2'? – bheklilr

risposta

7

Quello che sta accadendo è che quando hai specificato x di avere il tipo di Num a => a, il compilatore non può assolutamente sapere quale istanza di Num da utilizzare durante l'esecuzione 1 + 1. Quello che invece usa è l'impostazione predefinita. GHC definisce i tipi predefiniti per determinati tipi di caratteri, in modo tale che quando non è possibile determinare quale tipo concreto di utilizzo può dare risultati significativi senza generare errori. Quindi, quando si vede

> let x :: Num a => a 
|  x = 1 + 1 
> x 
2 
> :sprint x 
x = _ 

Questo perché GHCi sceglie Integer come il suo tipo di default per Num, ma quando si esegue questa operazione non memorizza il risultato in x s' posizione di memoria, dal momento che non v'è un modo per sapere se questa è anche la risposta corretta. Questo è il motivo per cui vedi x = _ da :sprint, non ha effettivamente valutato x :: Num a => a, è valutato x :: Integer. È anche possibile confusione con questa impostazione predefinita se stessi:

> newtype MyInt = MyInt Int deriving (Eq) 
> 
> instance Show MyInt where 
|  show (MyInt i) = show i 
> instance Num MyInt where 
|  (MyInt x) + (MyInt y) = MyInt (x - y) 
|  fromInteger = MyInt . fromInteger 
> 
> default (MyInt) 
> x 
0 

Così ora abbiamo detto che 1 + 1 = 0! Tenete presente che probabilmente non userete mai per questa funzionalità di GHC, ma è utile sapere.

+0

grande spiegazione +1 e grazie – Carsten

+0

btw: sul mio sistema GHCi imposterà' x' su '2 :: Integer' dopo averlo valutato! – Carsten