exception, not in IO

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

exception, not in IO

Ertugrul Söylemez
"Kees Bleijenberg" <k.bleijenberg at lijbrandt.nl> wrote:

> But sometimes the jsonString is not valid (misformed or wrong fields).
> decodeJSON then throws a exception.  I want to
>
> catch that exection and transform the result to something like ("" ,
> theErrorMsg). Unfortunately all catch functions want IO parameters.
>
> What can I do?

IO is just one of the many monads with exception support.  For your
case, since JSON parsing is a pure process, you would want to use a pure
exception monad like `Maybe` or `Either MyError`:

    data MyError
        = InvalidDateField
        | {- ... -}
        | UnknownError

There is nothing wrong with using regular exception types, if you wish,
in which case you might use `Either SomeException`.  Then separate
concerns:

    decode :: String -> Either MyError Glass
    encode :: Glass -> String

Finally the conversion function is as simple as:

    convert :: String -> Either MyError String
    convert = fmap encode . decode

If `encode` can fail as well and exceptions are regular Haskell
exceptions:

    import Control.Exception
    import Control.Monad

    decode :: String -> Either SomeException Glass
    encode :: Glass -> Either SomeException String

    convert :: String -> Either SomeException String
    convert = encode <=< decode

I hope this helps.


Greets,
Ertugrul

--
Not to be or to be and (not to be or to be and (not to be or to be and
(not to be or to be and ... that is the list monad.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://www.haskell.org/pipermail/beginners/attachments/20130714/a405caa4/attachment.pgp>

Reply | Threaded
Open this post in threaded view
|

exception, not in IO

Kees Bleijenberg
Ertugrul,

I don't understand all of it. This is what I've done

{-# LANGUAGE OverloadedStrings,DeriveDataTypeable #-}
module Test()
where

import Text.JSON
import Text.JSON.Generic
import Control.Exception
import Control.Monad

data Glass = Glass { a:: String,
                     b:: String} deriving (Show,Typeable,Eq,Data,Read)

data MyError = UnknownError deriving Show

glassDecode :: String -> (Either MyError Glass)
glassDecode s = Right ((decodeJSON s) :: Glass)
                   
glassEncode :: Glass -> Either MyError String
glassEncode g = return $ encodeJSON g

convert :: String -> Either MyError String
convert = glassEncode <=< glassDecode

test  = convert "{\"a\":\"blah\",\"b\":\"blahb\"}"
test2  = convert "{\"\":\"blah\",\"b\":\"blahb\"}"

If I call test I get back Right <theInputString>
If I call test2 (invalid string) I get Right "{*** Exception: fromJSON:
field does not exist a"
The good news is that the program doesn't halt any more.

How do I transform the last Right to a Left (without changing the source in
Text.JSON.Generic) if there is a error?  The code in Text.JSON.Generic calls
error "xxx" if something is wrong.

Kees



.....
IO is just one of the many monads with exception support.  For your case,
since JSON parsing is a pure process, you would want to use a pure exception
monad like `Maybe` or `Either MyError`:

    data MyError
        = InvalidDateField
        | {- ... -}
        | UnknownError

There is nothing wrong with using regular exception types, if you wish, in
which case you might use `Either SomeException`.  Then separate
concerns:

    decode :: String -> Either MyError Glass
    encode :: Glass -> String

Finally the conversion function is as simple as:

    convert :: String -> Either MyError String
    convert = fmap encode . decode

If `encode` can fail as well and exceptions are regular Haskell
exceptions:

    import Control.Exception
    import Control.Monad

    decode :: String -> Either SomeException Glass
    encode :: Glass -> Either SomeException String

    convert :: String -> Either SomeException String
    convert = encode <=< decode