1

这里有什么问题?

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)
4

1 回答 1

1

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

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

因为ainask没有明确的类型签名,所以 Haskell/GHC 从您使用它的方法推断它。

所以因为你有一个方法putStrLn a,所以唯一可能的方法是 if 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
于 2013-08-02T11:10:03.190 回答