如何识别Haskell递归函数共性并编写高阶函数捕获该模式?
识别Haskell递归函数的共同模式并编写高阶函数捕获它
嘿,咱们先把这四个函数拆解开,仔细看看它们的结构,很容易就能找到共同点:
先逐个拆解每个函数的核心逻辑:
f1:空列表返回1(乘法的单位元),遇到非空列表时,用乘法(*)把当前元素x和递归处理剩余列表的结果结合起来f2:空列表返回0,遇到非空列表时,不管当前元素是什么,都给递归结果加1(本质是统计元素个数)f3:空列表返回0(加法的单位元),遇到非空列表时,用加法(+)把当前元素x和递归结果结合f4:空列表返回**[]**(列表拼接的单位元),遇到非空列表时,用拼接操作(++)把当前元素x(这里x本身是列表)和递归结果结合
提炼共同模式
所有这些函数都遵循**右折叠(foldr)**的递归模板:
- 定义一个初始值(空列表时的返回结果)
- 定义一个二元结合函数,用来把当前列表元素和「处理剩余列表得到的累积结果」结合起来
- 递归遍历整个列表,用结合函数逐步累积结果
这个模式对应的高阶函数,其实Haskell标准库已经帮我们实现了,就是foldr,它的定义是:
foldr :: (a -> b -> b) -> b -> [a] -> b foldr _ init [] = init foldr f init (x:xs) = f x (foldr f init xs)
用foldr重写你的四个函数
现在我们可以用foldr把原来的四个函数简化成一行:
f1等价于foldr (*) 1(就是标准库的product函数)f2等价于foldr (\_ acc -> acc + 1) 0,或者更简洁的foldr (const (+1)) 0(对应标准库的length函数)f3等价于foldr (+) 0(就是标准库的sum函数)f4等价于foldr (++) [](对应标准库的concat函数)
为什么这个模式管用?
这个折叠模式本质上是把列表的递归遍历逻辑抽象出来了——我们只需要关心「初始值是什么」和「怎么把当前元素和累积结果结合」,不需要重复写递归的框架。这也是高阶函数的核心价值:捕获通用模式,减少重复代码。
内容的提问来源于stack exchange,提问作者realicado
相关产品推荐
相关产品推荐

