我正在研究使用haskell的一些函数式编程,我试图通过重新实现一些库函数来完成一些概念。
我有一个问题,但主要是关于什么时候选择递归迭代更好。例如,当重新实现“全部”功能时,我可以选择:
all1 :: (a -> Bool) -> [a] -> Bool
all1 p xs = foldr (\x acc -> acc && p x) True xs
all2 :: (a -> Bool) -> [a] -> Bool
all2 p (x:xs)
| p x == False = False
| otherwise = all2 p xs
我看待它的方式,递归的应该是更有效的时间,因为它将在第一个非匹配的条目停止,而折叠的一个更节省空间(我认为,仍然不清楚haskell中的尾递归优化)但它将始终扫描完整列表,除非通过查看false
总是在它出现后给false
这一事实做了一些聪明的优化。
那么,这种妥协是否始终存在?我是否误解了递归和折叠工作的方式?
谢谢!