没有由文字“0”产生“Num (IO ())”实例

Mii*_*iao 3 haskell

我正在实现一个简单的迭代斐波那契。为了测试它,我写了一个简单的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)

这意味着什么?

lef*_*out 6

您的使用尝试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)