Haskell中inits函数实现问题求助:输出不符合预期
修正你的Haskell
inits 函数实现 首先分析你的代码问题:
inits [] = [[]] inits (x:xs) = [x]: inits (xs)
处理[1,2]时,递归过程会生成[1] : ([2] : [[]]),最终得到[[1], [2], []]——这既颠倒了初始段的顺序,也没有生成包含当前元素与后续元素组合的初始段,完全不符合预期。
正确逻辑拆解
inits需要返回从空列表开始,依次包含前1个元素、前2个元素……直到整个列表的所有初始段。对于非空列表(x:xs):
- 所有列表的初始段都包含空列表
[] xs的每一个初始段,在头部添加x后,就变成了(x:xs)的非空初始段(比如xs的[]变成[x],xs的[2]变成[1,2])
修正后的代码
inits [] = [[]] inits (x:xs) = [] : map (x:) (inits xs)
递归过程验证
以inits [1,2]为例:
inits [1,2]→[] : map (1:) (inits [2])inits [2]→[] : map (2:) (inits [])→[] : [[2]]→[[], [2]]map (1:) [[], [2]]→[[1], [1,2]]- 最终拼接得到
[] : [[1], [1,2]]→[[], [1], [1,2]],完全符合预期。
更直观的写法(用let绑定)
如果觉得map不够直观,可以用let把子列表的初始段存起来,再逐步处理:
inits [] = [[]] inits (x:xs) = let subInits = inits xs in [] : map (x:) subInits
这样能清晰看到逻辑:先获取子列表的所有初始段,把x加到每个子初始段头部,再加上空列表,就是当前列表的完整初始段集合。
内容的提问来源于stack exchange,提问作者Roni
相关产品推荐
相关产品推荐

