2014-07-16 21 views
16

Sto solo imparando Haskell e IO monadi. Mi chiedo perché non avrebbe questa forza al programma di uscita "hi" e "bye":Perché Haskell non può essere indotto a eseguire operazioni di I/O utilizzando una valutazione rigorosa?

second a b = b 
main = print ((second $! ((print "hi") >>= (\r -> return()))) "bye") 

Per quanto ho capito, l'operatore $! costringerebbe il primo argomento di second da valutare e l'operatore >>= dovrebbe eseguire print "hi" per ottenere un valore da esso e passarlo a \r -> return(), che stamperebbe "ciao" allo schermo.

Cosa c'è di sbagliato nel mio ragionamento?

E inoltre, esiste un modo per dimostrare che Haskell non può essere ingannato (oltre all'uso di funzioni non sicure) nell'esecuzione di operazioni IO all'interno di codice "sicuro"?

+5

BTW, il tuo codice può essere semplificato in 'main = print (stampa" hi "\' seq \ '" ciao ")' –

+7

Risposta: Perché non puoi ingannare Haskell. –

risposta

33

L'espressione che si sta forzando è ((print "hi") >>= (\r -> return())), che è di tipo IO(). In quanto tale rappresenta un'azione IO. Ma valutazione una cosa del genere è molto diversa da in esecuzione it!

La valutazione di un valore indica l'esecuzione di un numero sufficiente di passaggi per trasformarlo in quello che viene chiamato weak head normal form. Poiché IO è astratto, è un po 'complicato vedere cosa significa in questo caso, ma si può pensare a IO a come RealWorld -> (a, RealWorld), e quindi la forma normale debole è, beh, una funzione in attesa di essere data RealWorld.

L'esecuzione implica la valutazione, ma anche l'argomento RealWorld viene passato come argomento, causando così l'effetto IO.

Tutto questo non è molto specifico per IO; la tua confusione ei concetti si applicano allo stesso modo a a -> b. Se capisci cosa fa $! quando il secondo argomento è una funzione, capirai cosa succede quando si tratta di un'azione IO.

21

Stai confondendo valutazione con esecuzione. Quando si forza un'espressione come print "hi", ciò non stampa nulla. Produce semplicemente un valore (in questo caso, un valore di tipo IO()) che rappresenta l'azione di stampa di qualcosa. Puoi pensare al valore di print "hi" come ricetta per la stampa di "ciao".