2

我正在寻找斐波那契数列的总和。这就是我坚持的地方:

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

main = do putStrLn "Enter a number:"
          num <- readLn
          foldr (+) 0 (take num fibs)

错误是:

No instance for (Num (IO t0))
  arising from the literal `0'
Possible fix: add an instance declaration for (Num (IO t0))
In the second argument of `foldr', namely `0'
In the expression: foldr (+) 0 (take num fibs)
In the expression:
  do { putStrLn "Enter a number:";
       num <- readLn;
       foldr (+) 0 (take num fibs) }

我到底哪里错了?

4

1 回答 1

6

您可能想要print结果:

main = do putStrLn "Enter a number:"
          num <- readLn
          print $ foldr (+) 0 (take num fibs)

错误消息的原因是do块中的每个语句都必须属于同一个 monad。在 的情况下main,就是IO。但是,foldr这里的结果是一个数字,而不是一个IO动作。

错误消息令人困惑,因为 GHC 以其智慧得出的结论是IO行动必须是数字,这当然是无稽之谈。

当你遇到一个令人困惑的类型错误时,在一些涉及的表达式中添加一些类型注释通常很有用,向 GHC 解释你所期望的类型。这通常会给您从 GHC 返回的更好的错误消息。

例如,如果您:: Integer在行尾添加foldr,您将收到以下消息:

Couldn't match expected type `IO b0' with actual type `Integer'
In a stmt of a 'do' block: foldr (+) 0 (take num fibs) :: Integer
In the expression:
  do { putStrLn "Enter a number:";
       num <- readLn;
         foldr (+) 0 (take num fibs) :: Integer }
In an equation for `main':
    main
      = do { putStrLn "Enter a number:";
             num <- readLn;
               foldr (+) 0 (take num fibs) :: Integer }

在这里更容易看到问题。GHC 期待一个类型声明IO b0,而你给了它一个Integer.

于 2013-05-29T21:51:17.263 回答