How do exceptions work in Haskell (part two)? -


i have following code:

{-# language derivedatatypeable #-} import prelude hiding (catch) import control.exception (throwio, exception) import control.monad (when) import data.maybe import data.word (word16) import data.typeable (typeable) import system.environment (getargs)  data argumentparserexception = wrongargumentcount | invalidportnumber     deriving (show, typeable)  instance exception argumentparserexception  data arguments = arguments word16 filepath string  main =     args <- return []     when (length args /= 3) (throwio wrongargumentcount)      let [portstr, cert, pw] = args     let portint = readmaybe portstr :: maybe integer     when (portint == nothing) (throwio invalidportnumber)      let portnum = fromjust portint     when (portnum < 0 || portnum > 65535) (throwio invalidportnumber)      return $ arguments (frominteger portnum) cert pw  -- newer 'base' has text.read.readmaybe alas, doesn't come -- latest haskell platform, let's not rely on readmaybe :: read => string -> maybe readmaybe s = case reads s of     [(x, "")] -> x     _         -> nothing 

its behavior differs when compiled optimizations on , off:

crabgrass:~/tmp/signserv/src% ghc -fforce-recomp main.hs && ./main main: wrongargumentcount crabgrass:~/tmp/signserv/src% ghc -o -fforce-recomp main.hs && ./main main: main.hs:20:9-34: irrefutable pattern failed pattern [portstr, cert, pw] 

why this? aware imprecise exceptions can chosen arbitrarily; here choosing 1 precise , 1 imprecise exception, caveat should not apply.

i agree hammar, looks bug. , seems fixed in head since time. older ghc-7.7.20130312 today's head ghc-7.7.20130521, wrongargumentcount exception raised , other code of main removed (bully optimiser). still broken in 7.6.3, however.

the behaviour changed 7.2 series, expected wrongargumentcount 7.0.4, , (optimised) core makes clear:

main.main1 =   \ (s_a11h :: ghc.prim.state# ghc.prim.realworld) ->     case ghc.list.$wlen            @ ghc.base.string (ghc.types.[] @ ghc.base.string) 0     of _ {       __default ->         case ghc.prim.raiseio#                @ ghc.exception.someexception @ () main.main7 s_a11h         of _ { (# new_s_a11k, _ #) ->         main.main2 new_s_a11k         };       3 -> main.main2 s_a11h     } 

when length of empty list different 3, raise wrongargumentcount, otherwise try rest.

with 7.2 , later, evaluation of length moved behind parsing of portstr:

main.main1 =   \ (eta_xw :: ghc.prim.state# ghc.prim.realworld) ->     case main.main7 of _ {       [] -> case data.maybe.fromjust1 of wild1_00 { };       : ds_dty ds1_dtz ->         case ds_dty of _ { (x_aoz, ds2_dta) ->         case ds2_dta of _ {           [] ->             case ds1_dtz of _ {               [] ->                 case ghc.list.$wlen                        @ [ghc.types.char] (ghc.types.[] @ [ghc.types.char]) 0                 of _ {                   __default ->                     case ghc.prim.raiseio#                            @ ghc.exception.someexception @ () main.main6 eta_xw                     of wild4_00 {                     };                   3 -> 

where

main.main7 =   text.parsercombinators.readp.run     @ ghc.integer.type.integer main.main8 main.main3  main.main8 =   ghc.read.$freadinteger5     ghc.read.$freadinteger_$sconvertint     text.parsercombinators.readprec.minprec     @ ghc.integer.type.integer     (text.parsercombinators.readp.$fmonadp_$creturn        @ ghc.integer.type.integer)  main.main3 = case lvl_r1ys of wild_00 { }  lvl_r1ys =   control.exception.base.irrefutpaterror     @ ([ghc.types.char], [ghc.types.char], [ghc.types.char])     "except.hs:21:9-34|[portstr, cert, pw]" 

since throwio supposed respect ordering of io actions,

the throwio variant should used in preference throw raise exception within io monad because guarantees ordering respect other io operations, whereas throw not.

that should not happen.

you can force correct ordering using noinline variant of when, or performing effectful io action before throwing, seems when inliner sees when nothing except possibly throwing, decides order doesn't matter.

(sorry, not real answer, try fit in comment ;)


Comments

Popular posts from this blog

blackberry 10 - how to add multiple markers on the google map just by url? -

php - guestbook returning database data to flash -

delphi - Dynamic file type icon -