由于 foldr 主要未编译

Main not compiling due to foldr

我已将这段代码添加到 f.hs 文件中:

main = foldr (+) (0) [1,2,3]

当我使用时:

:l f.hs

我收到错误:

[1 of 1] Compiling Main             ( f.hs, interpreted )

f.hs:1:14:
    No instance for (Num (IO t0)) arising from a use of ‘+’
    In the first argument of ‘foldr’, namely ‘(+)’
    In the expression: foldr (+) (0) [1, 2, 3]
    In an equation for ‘main’: main = foldr (+) (0) [1, 2, 3]
Failed, modules loaded: none.

我想使用 trace 并查看 fold 的输出。

为什么这段代码无法编译?

main 的类型为 IO (),而 foldr (+) (0) [1,2,3] 的类型为 Num a => a。 GHC 试图将它们结合起来但失败了,因为 Num 没有在 IO a 上定义。据推测,您想打印结果。试试这个

main = print $ foldr (+) (0) [1,2,3]

然后,一旦你加载到 GHCi,你可以调用 main 来获得 6

main的类型要与IO a类型统一。但是 foldr (+) (0) [1,2,3] 的类型是 Num a => a

您可以这样修改您的程序:

-- Note print return a value of type IO ()
main :: IO ()
main = print $ foldr (+) 0 [1,2,3] 

我可以重现并解决问题。我发现 http://www.quora.com/Why-cant-functions-be-defined-on-the-GHCi-repl 给了我提示: 正如其他答案中所述,REPL 似乎是 "a do block in the IO monad."。 do 表示法可用于表达一系列依次执行的单子表达式。作为it can be seen at Wikibooks,它可以被翻译成一串monad bind操作。

因此你有两个选择:

一个是让main有签名main :: IO (),这样

main :: IO ()
main = print $ foldr (+) (0) [1,2,3]

evaluateTwice :: IO()
evaluateTwice = do 
              main
              main
-- equvalent alternative as monadic bind operations, see Wikibooks
evaluateTwice = main >>= \ x1 -> main

将对 IO monad 的 main 进行两次调用(使用绑定),返回 IO monad 的新实例。这就是其他发帖者的基本建议。

或者您可以使用 let

let main = foldr (+) (0) [1,2,3]

定义了一个"variable".