Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell: Is there a way to deduce the return type of a function from inside the function?

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?

like image 467
Daniel Schmitz Avatar asked Dec 18 '14 13:12

Daniel Schmitz


1 Answers

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))
like image 193
max taldykin Avatar answered Oct 29 '22 14:10

max taldykin