Control.Exception
è progettato per l'uso:
- in un codice altrimenti puro in cui l'aggiunta di una monade legata all'errore o di un'altra struttura di segnalazione degli errori sarebbe troppo ingombrante
- nei casi in cui un thread o processo deve sollevare un'eccezione asincrona in un altro processo, al di fuori dei vincoli del sistema di tipi.
Per un esempio del primo, prendi la divisione per 0 nel tipo Int
(ad esempio div 3 0
). In questo caso non puoi dare una risposta ragionevole, ma non vuoi che il tuo operatore di divisione restituisca un Maybe Int
- potrebbe rendere i programmatori infelici! Quindi potresti usare un'eccezione per fermare il calcolo.
In questa situazione, potresti anche utilizzare error
per un effetto simile. La differenza è che Control.Exception
ti dà più flessibilità per catturare e segnalare ciò che è successo. Ma tali eccezioni possono essere catturate solo nella monade IO, che potrebbe imporre un onere al tuo cliente. Pertanto, ti suggerisco di salvarli per situazioni davvero eccezionali, forse catastrofiche.
Il materiale in Control.Monad.Error
funziona tramite una monade e utilizza il meccanismo di associazione / sequenziamento monadico per passare l'errore. Non sovverte il sistema di tipi come fa throw
, quindi ha le virtù di purezza e trasparenza relativa che lo fanno. Inoltre ti dà più flessibilità per gestire e recuperare dagli errori, e può anche rendere più facile passare gli errori al client se stai scrivendo una libreria (vedi Parsec e polyparse, che trasformano entrambi un errore + risultato monadico in una valore quando hanno finito, sebbene polyparse usi qualcosa di leggermente diverso da Control.Monad.Error
). Ma ovviamente devi lavorare all'interno della monade di gestione degli errori, o avvolgere un trasformatore monade che gestisce gli errori attorno a qualsiasi monade esistente in cui potresti lavorare. Entrambe le opzioni possono rendere il tuo codice considerevolmente più complesso.
Se non lo hai già fatto, consulta Real World Haskell, Capitolo 19 per una carrellata di questi e altre opzioni di gestione degli errori, e vedi alla fine del Capitolo 18 per alcuni dei più generali svantaggi dell'uso di monadi e trasformatori monadi.