2012-12-07 8 views
10

As shown in this answer, seq combinato con undefined fa cose molto strane quando si tratta di ragionamento equo, ad esempio può far fallire qualsiasi monade. Un altro esempio è in this question.È `evaluate` safe rispetto a` seq`?

Recentemente mi sono imbattuto in evaluate :: a -> IO a che fa una cosa simile: valuta il suo argomento su WHNF ma solo quando viene valutata l'azione IO. Questo sembra essere molto più sicuro, poiché ci si aspetta che "in IO possiamo fare tutto". Ovviamente non può essere usato ovunque, ma spesso la necessità di valutare un'espressione è in qualche modo connessa con un'operazione IO (come forzare un thread di produzione per valutare un calcolo invece di un thread di consumo quando si lavora con MVar s).

Quindi mi piacerebbe chiedere, quanto è sicuro evaluate? È possibile creare degli esempi (coinvolgere lo IO ovviamente) dove si interrompe il ragionamento sul codice come seq? O posso considerarlo come una sostituzione sicura di seq (se è possibile per un particolare programma)?

risposta

5

No, si verificano ancora gli stessi problemi causati dal comando seq, in quanto qualsiasi monade utilizzata nel primo argomento di evaluate avrà le sue regole di monade interrotte. Basando fuori la regola in risposta di ertes:

Nella categoria Kleisli monade genera return è il morfismo identità e (<=<) è la composizione. Quindi return deve essere un identità (<=<):

return <=< x = x 

Questo significa che si dovrebbe essere in grado di sostituire return <=< x con x con qualsiasi monade valida senza cambiare il funzionamento del programma.

Uso che con la funzione evaluate ...

evaluate (return <=< undefined :: a -> Identity b) >> putStrLn "hello" 

uscite ciao. Utilizzando quello che dovrebbe essere una dichiarazione equivalente sostituendo return <=< undefined con undefined:

evaluate (undefined :: a -> Identity b) >> putStrLn "hello" 

provoca invece un'eccezione Prelude.undefined.

Ciò accade solo con la funzione di valutazione. Si noti che return ha esattamente la stessa firma del tipo di evaluate. Se si sostituisce evaluate con return nei comandi precedenti, l'azione risultante per entrambi i comandi è la stessa (viene emessa hello).