In GHCi:
Prelude> error (error "")
*** Exception:
Prelude> (error . error) ""
*** Exception: *** Exception:
Perché la prima non è un'eccezione annidata?
In GHCi:
Prelude> error (error "")
*** Exception:
Prelude> (error . error) ""
*** Exception: *** Exception:
Perché la prima non è un'eccezione annidata?
error
è speciale e non è proprio un meccanismo di eccezione. Per le eccezioni reali e catturabili vedere Error
monade.
(\f g x -> f (g x)) error error ""
si comporta in modo diverso da (.) error error ""
, anche se quella funzione è equivalente a (.)
. Forse ha a che fare con i flag di ottimizzazione con cui è stato compilato Prelude.
iterate error "" !! n
e il fantastico fix error
.
error = error
e programma di conseguenza.
Risposte:
La risposta è che questa è la semantica (alquanto sorprendente) delle eccezioni imprecise
Quando è possibile mostrare che il codice puro restituisce un insieme di valori eccezionali (cioè il valore di error
o undefined
, ed esplicitamente non il tipo di eccezioni generate in IO ), il linguaggio consente di restituire qualsiasi valore di quell'insieme. I valori eccezionali in Haskell sono più simili NaN
al codice in virgola mobile, piuttosto che alle eccezioni basate sul flusso di controllo nei linguaggi imperativi.
Un trucco occasionale anche per Haskeller avanzati è un caso come:
case x of
1 -> error "One"
_ -> error "Not one"
Poiché il codice valuta una serie di eccezioni, GHC è libera di sceglierne una. Con le ottimizzazioni attive, potresti scoprire che restituisce sempre "Non uno".
Perché lo facciamo? Perché altrimenti vincoleremmo eccessivamente l'ordine di valutazione della lingua, ad es. Dovremmo fissare un risultato deterministico per:
f (error "a") (error "b")
ad esempio, richiedendo che venga valutato da sinistra a destra se sono presenti valori di errore. Molto poco Haskelly!
Poiché non vogliamo paralizzare le ottimizzazioni che possono essere fatte sul nostro codice solo per supportarlo error
, la soluzione è specificare che il risultato è una scelta non deterministica dall'insieme di valori eccezionali: eccezioni imprecise! In un certo senso, tutte le eccezioni vengono restituite e una viene scelta.
Normalmente, non ti interessa - un'eccezione è un'eccezione - a meno che non ti interessi della stringa all'interno dell'eccezione, nel qual caso l'uso error
per il debug è altamente confuso.
Riferimenti: una semantica per eccezioni imprecise , Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Progettazione e implementazione dei linguaggi di programmazione Proc (PLDI'99), Atlanta. ( PDF )
throw
) e con cui puoi generare un'eccezione in modo deterministico throwIO
.
case error "banana" of (x:xs) -> error "bonobo"
posso darti * Exception: bonobo
.