这里有什么问题?
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)
答案 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