假设我有以下功能:
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)
它将String解析为我想要的任何内容。 如果字符串格式错误,则会抛出一个异常,显示无法解析的消息。
我在IO-Monad的do块中使用此函数,如
(a,b) <- parse msg :: IO (Int,Int)
并在
等其他地方s <- parse msg :: IO String
现在,如果我想让异常更详细,报告哪种类型无法阅读
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))
我如何得到类型为b的东西?
可能的解决方法是执行此操作
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))
并像
一样调用它s <- parse "" msg :: IO String
但这看起来很傻。
有没有办法从函数内部推导函数的返回类型?
答案 0 :(得分:12)
您不需要虚拟变量,可以使用ScopedTypeVariables
扩展名。
{-# 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))