function - 使用折叠插入
问题描述
有人可以解释一下如何intercalate
使用 fold 编写函数吗?此外,我听说过foldr
or foldl
; 在这种情况下,哪一个最适合使用?
这是我的递归尝试:
intercalate :: [a] -> [[a]] -> [a]
intercalate s [] = []
intercalate s [x] = x
intercalate s (x:xs) = x ++ s ++ (intercalate s xs)
解决方案
使用foldr1
:
intercalate' :: [a] -> [[a]] -> [a]
intercalate' _ [] = []
intercalate' x xs = foldr1 (\a acc -> a ++ x ++ acc) xs
这将在每个元素之间插入右侧的值。x
(尽管它懒惰地这样做。-直到需要时才评估整个折叠。)
两者foldr1
和foldr
的相似之处在于它们从右侧折叠。不同之处在于前者不需要我们提供最终期限,而后者确实需要提供最终期限。这需要我们对空列表进行模式匹配,否则会抛出异常。
的确,foldl1
也可以做到插层。但是,强烈建议不要这样做,因为左折叠会急切地消耗输入。
intercalate' :: [a] -> [[a]] -> [a]
intercalate' _ [] = []
intercalate' x xs = foldl1 (\acc a -> acc ++ x ++ a) xs
为了进一步强调对正确折叠的偏好,请考虑以下组成:
take 10 . intercalate' [0] $ repeat [1..3]
看起来无害。但是使用foldl1
会急切地消耗无限列表,而不是停止进程。
但是, usingfoldr1
将延迟评估并给出正确的结果[1,2,3,0,1,2,3,0,1,2]
。(在询问前导词和评估折叠之前intercalate'
会临时评估。)[1..3] ++ [0] ++ (foldr (...) [0] [elem1 ... elemN])
take 10
向威尔致敬。
有用的阅读:
foldl
与foldr
无限列表的行为对比
推荐阅读
- html - CSS - 计时器插件不会显示完整
- c# - 如何在 C# 中创建一个无法退出的屏幕
- java - 如何只接受来自 JTextField 的指定模式?
- sublimetext3 - ST3中自动缩进/重新缩进代码块的键绑定
- c - 检查所有元素是否与分而治之相同
- regex - 如何进行服务器和客户端验证,它应该只接受文本框中的 URL?
- javascript - 函数逻辑对 javascript 时钟应用程序没有意义
- c# - ASP.NET MVC 如何在同一解决方案中使用另一个项目中的函数
- identityserver4 - 移动了我的登录页面,现在无法登录
- magento - N98 magerun 命令问题 - Magento 1.9x