Perché dovrei usare Control.Exception in Haskell?

4

Sto cercando di padroneggiare veramente la gestione degli errori di Haskell e sono arrivato al punto in cui non capisco perché utilizzare Control.Exception invece di Control.Monad.Error.

Per come posso vederlo, posso catturare eccezioni Control.Monad.Error in contesti puri e impuri. Al contrario, le eccezioni definite in Control.Exception possono essere catturate solo in contesti impuro / IO.

Dato che forniscono due interfacce e semantica separate che avrei bisogno di memorizzare, in quali circostanze avrei bisogno di Control.Exception invece di Control.Monad.Error?

    
posta Savanni D'Gerinel 04.01.2013 - 23:47
fonte

1 risposta

6

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.

    
risposta data 06.01.2013 - 08:16
fonte

Leggi altre domande sui tag