考虑下面的代码,它返回一个数字的阶乘:
factorial n = go n 1
where
go n ret | n > 1 = go (n-1) (ret * n)
| otherwise = ret
如何打印 n
在 go n ret
的每个递归调用中?由于n
每次都在递减,我想看看是否可以在每次递减时打印它(如 5 4 3 2 1
)。这就是我尝试这样做的方式(这是完全错误的),但我想不出不同的方式:
factorial n = go n 1
where
go n ret | n > 1 = go (n-1) (ret * n) print n
| otherwise = ret
最佳答案
方式
要打印,您需要将值提升到 I/O 应用程序;类型将从
factorial :: (Num a, Ord a) => a -> a
到factorial :: (Num a, Ord a, Show a) => a -> IO a
什么go
行动确实go
action需要做两件事:n
go
或产生结果如何顺序执行两个 I/O 操作
为了做两件事,我们需要一些组合器来组合它们。这里合适的是
*>
:
(*>) :: Applicative f => f a -> f b -> f b
Sequence actions, discarding the value of the first argument.
这正是我们所需要的,因为我们不需要使用第一个 Action 的值(
print
Action 的类型是 IO ()
,因此它不包含任何有用的结果)。将值提升到 I/O
我们还需要
pure
在末尾
pure :: Applicative f => a -> f a
Lift a value.
将结果提升到 I/O 应用程序中。
编码
factorial n = go n 1
where
go n acc =
print n *>
if n > 1
then let !acc' = acc * n
in go (n-1) acc'
else pure acc
!
在 acc'
的绑定(bind)中forces立即发生乘法(感谢 Daniel Wagner 指出需要这样做)。在 GHCi 中进行测试:
λ> factorial 5 >>= print
5
4
3
2
1
120
关于haskell - 如何在 Haskell 递归调用中打印迭代?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48845646/