Suppose I've got the following function:
import Data.Typeable
import Text.Read (reads)
parse :: (Read b, Typeable b) => String -> IO b
parse msg = case reads msg of
[(value,"")] -> return value
_ -> throwIO $ ErrorCall ("could not parse " ++ msg)
It parses a String into whatever I want it to. If the String is malformed it throws an exception showing the message, that failed to parse.
I use this function in a do block of the IO-Monad like
(a,b) <- parse msg :: IO (Int,Int)
and at another place like
s <- parse msg :: IO String
Now, if I want to to make the exception more verbose reporting which type it failed to read
import Data.Typeable
import Text.Read (reads)
parse :: (Read b, Typeable b) => String -> IO b
parse msg = case reads msg of
[(value,"")] -> return value
_ -> throwIO $ ErrorCall ("could not parse " ++ msg ++ " as " ++
show ( typeOf something_that_has_type_b))
how do I get something, that has type b?
A possible workaround would be doing this
import Data.Typeable
import Text.Read (reads)
parse :: (Read b, Typeable b) => b -> String -> IO b
parse dummy msg = case reads msg of
[(value,"")] -> return value
_ -> throwIO $ ErrorCall ("could not parse " ++ msg ++ " as " ++
show ( typeOf dummy))
and invoking it like
s <- parse "" msg :: IO String
But that looks quite silly.
Is there a way to deduce the return type of a function from inside the function?
You don't need dummy variable, you can use ScopedTypeVariables
extension.
{-# LANGUAGE ScopedTypeVariables #-}
parse :: forall b. (Read b, Typeable b) => String -> IO b
parse msg = case reads msg of
[(value,"")] -> return value
_ -> error $ "could not parse " ++ msg ++ " as " ++
show (typeOf (undefined :: b))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With