我正在实现一个简单的迭代斐波那契。为了测试它,我写了一个简单的main
:
fib n = i where (i, _) = foldl (\(i, j) _ -> (j, i + j)) (0, 1) [1..n]
main = do
foldl (\_ n -> print $ fib n) 0 [0, 5, 10]
Run Code Online (Sandbox Code Playgroud)
...并出现错误!
* No instance for `Num (IO ())' arising from the literal `0'
* In the second argument of `foldl', namely `0'
In a stmt of a 'do' block:
foldl (\ _ n -> print $ fib n) 0 [0, 5, 10]
In the expression: do foldl (\ _ n -> print $ fib n) 0 [0, 5, ....]
Run Code Online (Sandbox Code Playgroud)
这意味着什么?
您的使用尝试foldl (\_ n -> print $ fib n)
还不错,但是用 初始化它是没有意义的0
。为什么0
?
您在这里构建的是打印各种内容的操作。行动不是数字。“空动作”是pure ()
main = do
foldl (\_ n -> print $ fib n) (pure ()) [0, 5, 10]
Run Code Online (Sandbox Code Playgroud)
这种类型检查并不能满足您的要求:与其他语言不同,它print
没有副作用,但需要显式地与main
操作相关联。在这种情况下,您可以累积地执行此操作,从 开始b = pure ()
,然后使用 绑定第一个print
到它>>
,依此类推。
main = do
foldl (\b n -> b >> print (fib n)) (pure ()) [0, 5, 10]
Run Code Online (Sandbox Code Playgroud)
...这确实会打印所有三个结果。
然而,更具可读性的替代方案是
main = sequence [print $ fib n | n <- [0, 5, 10]]
Run Code Online (Sandbox Code Playgroud)
或者
main = mapM_ (print . fib) [0, 5, 10]
Run Code Online (Sandbox Code Playgroud)