Sto giocando con le eccezioni in haskell e sono incappato in una cosa che non riesco ancora a capire.Gestione delle eccezioni generate da codice puro con `try`
In GHCi faccio:
Prelude Control.Exception> let thrower = (read "A") :: Int
Prelude Control.Exception> :{
Prelude Control.Exception| let main = do
Prelude Control.Exception| x <- (try $ return thrower) :: IO (Either SomeException Int)
Prelude Control.Exception| print x
Prelude Control.Exception| :}
Prelude Control.Exception> main
Questo definisce thrower
, la mia espressione di test che non riuscirà ad eccezione.
Poi definiscono main
che avvolge tale espressione in try
(avvolgendolo in IO
prima, poiché try
accetta IO
) e quindi scarta da IO
(prodotto da try
) e print
s esso.
Tutto sembra grande finora - valutare main
in repl restituisce eccezione avvolti in entrambi i casi:
Right *** Exception: Prelude.read: no parse
Tuttavia, se provo a compilare ed eseguire lo stesso codice come un app:
module Main where
import Control.Exception
thrower = (read "A") :: Int
main = do
x <- (try $ return thrower) :: IO (Either SomeException Int)
print x
... si blocca con eccezione:
haskelltest.exe: Prelude.read: no parse
Sembra li eccezione ke scivolò oltre try
.
Cosa mi manca qui e qual è il modo corretto di gestirlo?
Come nota a margine per chiunque abbia una situazione simile, nella mia app effettiva non è stato sufficiente "valutare" l'espressione in WHNF e ho dovuto usare anche 'force' (http://hackage.haskell.org /packages/archive/deepseq/latest/doc/html/Control-DeepSeq.html#v:force) –
@EugenyLoy: poi di nuovo, come ho detto, probabilmente non dovresti usare le eccezioni. Con un errore corretto monad l'intero problema non si pone in primo luogo, e il risultato viene valutato esattamente nel modo più approfondito necessario per assicurarsi che non ci siano errori. – leftaroundabout