如何为Haskell的dropTake函数补充≤2n元素时保留全部的逻辑?
修正后的dropTake函数实现
先给出完整的可运行代码:
dropTake :: Int -> [a] -> [a] dropTake n lst | n <= 0 = error "n必须是正整数" | len <= 2*n = lst | otherwise = take n lst ++ drop (len - n) lst where len = length lst
你的初始实现存在的问题
- 元素重复问题:当列表长度≤2n时,你的代码会强行拼接前n个和后n个元素,导致中间元素重复。比如你的示例中,列表长度7、n=4,2n=8,本应返回全部元素,但你的代码会输出
[0,1,2,3,3,4,5,6],多了一个重复的3。 - 边界情况未处理:没有覆盖n=0的场景,此时会触发非-exhaustive patterns错误。
修正逻辑说明
- 先计算列表总长度
len,用where子句复用该值,避免重复计算。 - 新增长度判断:如果列表长度≤2n,直接返回原列表,完全符合需求中"保留所有元素"的规则。
- 当列表长度大于2n时,用
take n获取前n个元素,用drop (len - n)获取最后n个元素(因为跳过前len-n个元素后,剩下的正好是末尾n个),两者拼接即可得到目标结果。 - 统一处理n≤0的情况(包括负数和0),抛出明确的错误提示。
测试验证
- 你的示例:
dropTake 4 [0,1,2,3,4,5,6]→ 返回原列表[0,1,2,3,4,5,6],符合预期。 - 长列表测试:
dropTake 3 [0,1,2,3,4,5,6,7,8,9]→ 返回[0,1,2,7,8,9],正确保留前后3个元素。 - 短列表测试:
dropTake 2 [1,2,3]→ 返回[1,2,3],符合长度≤2n时保留全部的规则。
内容的提问来源于stack exchange,提问作者txm03
相关产品推荐
相关产品推荐

