我已将此代码添加到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的输出。
为什么这段代码没有编译?
答案 0 :(得分:5)
main
的类型为IO ()
,而foldr (+) (0) [1,2,3]
的类型为Num a => a
。 GHC尝试将这些组合但失败,因为Num
未定义IO a
。据推测,您想要打印结果。试试这个
main = print $ foldr (+) (0) [1,2,3]
然后,加载到GHCi后,您可以致电main
获取6
。
答案 1 :(得分:3)
主要类型应与类型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]
答案 2 :(得分:0)
我可以重现并解决问题。我发现http://www.quora.com/Why-cant-functions-be-defined-on-the-GHCi-repl给了我提示:
似乎REPL是" IO monad中的阻止。"如其他答案中所述。
符号可以用来表达一系列一个接一个地执行的monadic表达式。作为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
将两个调用链接到main
monad的IO
(使用bind),返回IO
monad的新实例。这是其他海报基本上建议的。
或者,您可以使用let
let main = foldr (+) (0) [1,2,3]
定义了一个"变量"。