Haskell:有没有办法从函数内部推导函数的返回类型?

时间:2014-12-18 13:34:30

标签: haskell types polymorphism return-value

假设我有以下功能:

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

但这看起来很傻。

有没有办法从函数内部推导函数的返回类型?

1 个答案:

答案 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))