7

我正在使用以下实现maybeRead

maybeRead :: (Read a) => String -> Maybe a
maybeRead = fmap fst . listToMaybe . filter (null . dropWhile isSpace . snd) . reads

和我自己的getNum函数,它会提示直到它得到有效的输入:

getNum :: (Num a, Read a) => String -> IO a
getNum s = do
    putStr s
    input <- fmap maybeRead getLine
    if isNothing input
        then getNum s
        else return $ fromJust input

但是,如果我输入5.2它会将其视为错误输入 - 为什么?在我的代码中Int和的出现为零。Integer我只使用Num,因为我想接受任何类型的数字。

如果我明确地将其称为getNum "Enter a number: " :: IO Double,那么它可以工作。我必须这样做吗?Haskell 的类型系统是否只是在欺骗我认为我应该能够做到这一点,而实际上如果没有完整的动态类型是不可能的?如果是这样,那么为什么我的代码甚至可以编译;为什么它假设整数?

4

1 回答 1

14

您的函数确实会接受Integer,Float或任何其他Num实例。但是,它接受哪种类型,以及它如何解析String,并不是由它接收的输入决定的,而是由结果应该基于什么类型决定的。

假设您使用getNum并将结果值传递给需要Float; 在这种情况下,它将解析一个Float值。如果你将它传递给需要的东西Integer,它会解析它。

至于为什么它假设, Haskell Report 中指定了Integer模糊类型的“默认”系统,并且规则说具有约束的模糊类型应该默认为.NumInteger

于 2012-03-04T01:57:27.990 回答