是什么导致此程序中的解析错误?

时间:2013-08-02 10:50:37

标签: haskell

这里有什么问题?

module Main
    where

import System.IO

main = do
    hSetBuffering stdin LineBuffering
    numbers <- ask -- parse error on input `numbers'
    putStrLn "The sum of all numbers is:"
    putStrLn $ sum numbers
    putStrLn "The product of all numbers is:"
    putStrLn $ product numbers

ask :: (Read a, Eq a, Num a) => IO [a]
ask = do
    putStrLn "Enter a number to add it to the list. Enter zero to terminate the list."
    input <- getLine
    let n = read input
    if n == 0
    then return []
    else do
        rest <- ask 
        return (n : rest)

1 个答案:

答案 0 :(得分:1)

让我们看一下putStrLn的类型签名:

> :t putStrLn
putStrLn :: String -> IO ()

由于a中的ask没有明确的类型签名,Haskell / GHC会从您使用它的方法中推断出它。

因为您有方法putStrLn a,唯一可行的方法是a :: String

,在sum的类型签名中:

> :t sum
sum :: (Num a) => [a] -> a

a必须是Num类型类的实例。 (您的ask函数也指定了这一点。

GHC知道a 必须String ...但sum需要Num。至少在序言中,String不是Num的实例。

这就是矛盾出现的地方。

我建议您使用ghc-mod之类的程序来检查程序,您可能会收到更多有用的错误消息。这是我得到的:

No instance for (Num String)

与我们的结论很吻合。

在这种情况下,解决方案是先将Num转换为String

> :t show
show :: (Show a) => a -> String

有:

putStrLn $ show $ sum numbers

幸运的是,printStrLn . show的别名是print

> :t print
print :: (Show a) => a -> IO ()

所以你可以使用

print $ sum numbers