我已将此代码添加到f.hs文件:
main = foldr (+) (0) [1,2,3]
当我使用:
:l f.hs
I receive error:
[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似乎是"IO单子中的do块"。do表示法可用于表示一系列依次执行的一元表达式。在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
(使用bind),返回IO
monad的新实例。这是其他海报的基本建议。
也可以使用let
let main = foldr (+) (0) [1,2,3]
定义了一个变量