Haskell如何仅用递归实现字符串列表字符轮转且保留各字符串原有形态
Haskell
join函数实现问题 需求描述
需要实现签名为join :: [[a]] -> [[a]]的函数,功能规则如下:
- 将列表中每个字符串的首字符替换为前一个字符串的尾字符
- 首个字符串的尾字符补到最后一个字符串的末尾
- 处理后每个字符串的长度和原长度完全一致
预期运行示例
join ["m"] = ["m"] join ["a","b","c"] = ["b","c","a"] join ["goodday", "world", "i", "love", "haskell"] = ["ooddayw","orldi","l","oveh","askellg"] join ["the", "catcher", "in", "the", "rye"] = ["hec","atcheri","nt","her","yet"]
实现约束
- 仅可使用Haskell基础函数,不可调用额外库函数
- 仅允许使用递归语法实现
用户现有问题代码
join :: [[a]] -> [[a]] join [[a]] = [[a]] join (n:ns:nss) | null nss == False = ((i n ns) : k (ns:nss)) | otherwise = []
问题解答
需求可行性
该需求可以实现,符合Haskell的函数式编程逻辑。
现有代码存在的问题
- 模式覆盖不完整:仅覆盖了单元素列表、长度≥3的列表场景,缺少长度为2的列表的处理逻辑,当递归到只剩两个元素时会触发
otherwise分支返回空列表,直接丢失最后两个元素的处理结果。 - 核心逻辑未实现:代码中使用的
i、k辅助函数均未定义,没有实现「首字符替换为前一字符串尾字符」的核心逻辑。 - 未处理环形替换规则:需求要求第一个字符串的尾字符要补到最后一个字符串末尾,现有逻辑完全没有处理首尾关联的环形规则,最后一个元素无法获取第一个字符串的尾字符。
- 无长度保障逻辑:没有约束输出字符串的长度和输入一致,不符合需求要求。
合规实现代码(仅递归+基础函数)
首先实现三个基础辅助函数,均为递归实现,未调用任何外部库:
-- 取列表最后一个元素 last' :: [a] -> a last' [x] = x last' (_:xs) = last' xs -- 取列表除第一个元素外的后缀 tail' :: [a] -> [a] tail' (_:xs) = xs -- 主函数实现 join :: [[a]] -> [[a]] join [] = [] join [x] = [x] join all@(first:_) = go all (last' first) where -- 递归遍历处理相邻元素,firstLast缓存第一个元素的尾字符,最后给最后一个元素补尾 go [lastStr] firstLast = [tail' lastStr ++ [firstLast]] go (cur:next:rest) firstLast = (tail' cur ++ [last' next]) : go (next:rest) firstLast
上述代码运行结果完全匹配提供的预期示例,符合所有约束要求。
内容的提问来源于stack exchange,提问作者idontknowhowtocode
相关产品推荐
相关产品推荐

