2012-12-01 3 views
8

Ich fange immer noch an, Haskell zu erkunden. Ich weiß, dass dieser Code in der IO Monade "läuft". Wenn es von der l <- ... Zeile zur nächsten geht, wird die IO - bind aufgerufen.Warum ist das nicht faul

Man könnte denken, dass, weil Haskell faul ist, l nie ausgewertet wird. Aber "bind" wertet immer den vorherigen Befehl aus, ist das richtig? Weil das Programm den Fehler "Datei nicht gefunden" erzeugt.

main = do 
    l <- mapM readFile [ "/tmp/notfound" ] 
    return() 
+1

'l wird nie ausgewertet '- Hm? Faul heißt nicht "nie", sondern "noch nicht" oder "nur wenn es wirklich gebraucht wird". –

+1

@RobertHarvey Ja, aber für die Nicht-Haskeller, die den Quellcode betrachten, wird 'l' nicht mehr benutzt. Aber es wird implizit verwendet, oder? – Cartesius00

Antwort

15

Man könnte denken, dass da Haskell faul ist, wird die l nie ausgewertet.

Ja, und es wird nie ausgewertet. Aufgrund der Definition von (>>=) in IO wird jedoch die Aktion readFile "/tmp/notfound" ausgeführt, und das bedeutet, dass die Laufzeit versucht, die Datei zu öffnen. Wenn es keine solche Datei gibt, wird der Fehler "Datei nicht gefunden" angezeigt. Wenn es eine solche Datei gäbe, würde sie geöffnet werden, aber ihr Inhalt würde nicht gelesen werden, bis sie angefordert wird. Im obigen werden sie nicht verlangt, so dass die Inhalte nicht gelesen werden.

Was ist ausgewertet hier (und sogar ausgeführt) ist die Aktion l produzieren. Da die Datei nicht existiert, führt dies zu einem Fehler.

9

Wenn Sie die do Notation im Code erweitern, erhalten Sie:

main = (mapM readFile ["/tmp/notfound"]) >>= (\l -> return()) 

Also ja, l nie ausgewertet wird, aber das bedeutet nicht, dass der Aufruf von mapM nie ausgewertet wird. >>= muss immer seinen linken Operanden auswerten, um zumindest in gewissem Maße einen Wert zu erzeugen (zumindest in der IO-Monade und in jeder anderen Monade, die mir in den Sinn kommt).