Hello, dear List!
Super simple function - "safe enum conversion". It's based on `Either` because only it instantiates `MonadCatch` (Maybe does not, but with MaybeT I've got error that internal monad Indetity is not MonadCatch, so I avoid to use Maybe). That it is: data A = A1|A2 deriving (Enum, Show) data B = B1|B2|B3 deriving (Enum, Show) conv :: B -> Either SomeException A conv b = safeConv where catchError (e::SomeException) = Left e safeConv = (Right $ toEnum $ fromEnum b) `catch` catchError -- toRes (Left _) = Nothing -- toRes (Right r) = Just r But exception is not catching and I'm getting it in GHCI repl :) Exceptions are different?! What's wrong with this code? === Best regards, Paul _______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners |
I think that this might be related to where it says in the documentation that 'catch' must be called from inside the IO monad: http://hackage.haskell.org/package/base-4.10.1.0/docs/Control-Exception-Base.html#v:catch. That doc also points to the evaluate function for details on catching exceptions in pure code.
The reason it works in the GHCi repl is that GHCI is "special." Everything you evaluate it is in the IO monad/is implicitly in a 'do' block. This is why when you bind variables in GHCi you have to use 'let <defs>' rather than 'let <defs> in <expression>'. I think that what you're running into is that because your code is implicitly in an IO action in GHCi, you can catch the exception. In compiled code (I assume this is where it's breaking?) it's a pure function though. I'd like for someone else to chime in though, at the least maybe look into using evaluate. -Chris Baa writes: > Hello, dear List! > Super simple function - "safe enum conversion". It's based on `Either` > because only it instantiates `MonadCatch` (Maybe does not, but with > MaybeT I've got error that internal monad Indetity is not MonadCatch, > so I avoid to use Maybe). That it is: > > data A = A1|A2 deriving (Enum, Show) > data B = B1|B2|B3 deriving (Enum, Show) > conv :: B -> Either SomeException A > conv b = safeConv > where catchError (e::SomeException) = Left e > safeConv = (Right $ toEnum $ fromEnum b) `catch` catchError > -- toRes (Left _) = Nothing > -- toRes (Right r) = Just r > > But exception is not catching and I'm getting it in GHCI repl :) > Exceptions are different?! What's wrong with this code? > > === > Best regards, Paul > _______________________________________________ > Beginners mailing list > [hidden email] > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners _______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners |
Hello, Chris! Yes, you are right. Gabriel answered already too:
http://www.haskellforall.com/2012/07/errors-10-simplified-error-handling.html?showComment=1513269598213#c3541282127755203659 What I can't understand in this case is: if partial functions CAN raise "IO" exception CallError (I'm not sure in terminology here), and this exception can be catched only in IO monad, why is this not reflected in the types?! So, seems Haskell is not pure functional language, if there are such surprices. Sure, there are compromises but they can be reflected in types/signatures in some way :) Strange. Solution may be to use "spoon" package which uses `deepseq` to force to normal form but needs data to be NFData... Thanks to Gabriel for help :) === Best regards, Paul > I think that this might be related to where it says in the > documentation that 'catch' must be called from inside the IO monad: > http://hackage.haskell.org/package/base-4.10.1.0/docs/Control-Exception-Base.html#v:catch. > That doc also points to the evaluate function for details on catching > exceptions in pure code. > > The reason it works in the GHCi repl is that GHCI is "special." > Everything you evaluate it is in the IO monad/is implicitly in a 'do' > block. This is why when you bind variables in GHCi you have to use > 'let <defs>' rather than 'let <defs> in <expression>'. I think that > what you're running into is that because your code is implicitly in > an IO action in GHCi, you can catch the exception. In compiled code > (I assume this is where it's breaking?) it's a pure function though. > > I'd like for someone else to chime in though, at the least maybe look > into using evaluate. > > -Chris > > Baa writes: > > > Hello, dear List! > > Super simple function - "safe enum conversion". It's based on > > `Either` because only it instantiates `MonadCatch` (Maybe does not, > > but with MaybeT I've got error that internal monad Indetity is not > > MonadCatch, so I avoid to use Maybe). That it is: > > > > data A = A1|A2 deriving (Enum, Show) > > data B = B1|B2|B3 deriving (Enum, Show) > > conv :: B -> Either SomeException A > > conv b = safeConv > > where catchError (e::SomeException) = Left e > > safeConv = (Right $ toEnum $ fromEnum b) `catch` catchError > > -- toRes (Left _) = Nothing > > -- toRes (Right r) = Just r > > > > But exception is not catching and I'm getting it in GHCI repl :) > > Exceptions are different?! What's wrong with this code? > > > > === > > Best regards, Paul > > _______________________________________________ > > Beginners mailing list > > [hidden email] > > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > > _______________________________________________ > Beginners mailing list > [hidden email] > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners _______________________________________________ Beginners mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners |
Free forum by Nabble | Edit this page |