Come funzionano le eccezioni in Haskell?


86

In GHCi:

Prelude> error (error "")
*** Exception: 
Prelude> (error . error) ""
*** Exception: *** Exception: 

Perché la prima non è un'eccezione annidata?


9
Questa è una trasformazione che GHC può fare: "Io sono il compilatore che opera da solo e tutti gli _ | _ sono uguali per me". Stai chiedendo i dettagli di implementazione che rendono queste due righe compilabili in modo diverso?
shachaf

3
errorè speciale e non è proprio un meccanismo di eccezione. Per le eccezioni reali e catturabili vedere Errormonade.
Cat Plus Plus

1
Nota, ad esempio, che (\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.
shachaf

5
Inoltre iterate error "" !! ne il fantastico fix error.
Vitus

9
Fingo sempre questo error = errore programma di conseguenza.
Gabriel Gonzalez

Risposte:


101

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 erroro 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 NaNal 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 errorper 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 )


2
Capisco che GHC abbia scelto una delle eccezioni che potrebbero essere riscontrate. Ma nel tuo esempio "caso", l'eccezione "Non uno" non può essere rilevata per un input di 1, quindi lo classificherei comunque come un bug.
Peaker

8
@Peaker dead code elim - l'ottimizzatore non ha bisogno di guardare x per vedere che un errore è il risultato, tutti i rami producono lo "stesso" valore, quindi può ignorare completamente il valore di input. Non è un bug, salvo eccezioni imprecise!
Don Stewart

1
@lpsmith: Penso che tutti i tipi di eccezione siano imprecisi (se lanciati usando throw) e con cui puoi generare un'eccezione in modo deterministico throwIO.
FunctorSalad

4
@Peaker Penso che tu abbia ragione. Non credo che ghc dovrebbe ottimizzare questa espressione se vuole giocare secondo le regole stabilite nell'impreciso documento sulle eccezioni.
agosto

3
Che la carta eccezioni imprecise non sembra dire è che se il caso scrutinee è un valore di errore, poi valori di errore dai rami possono essere restituiti. Quindi case error "banana" of (x:xs) -> error "bonobo"posso darti * Exception: bonobo.
Ben Millwood,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.