Haskell自定义sep函数(类splitOneOf)实现及类型错误排查
搞定Haskell sep函数的类型匹配问题
嘿,我看到你备考期末时写这个类似splitOneOf的sep函数遇到了类型错误,咱们一起来把它解决掉!
需求回顾
你要实现的sep函数需要:
- 接收两个参数:分隔符列表和目标列表
- 检测并移除目标列表中的分隔符字符
- 返回分割后的元素列表的列表
- 示例:输入
sep " \t\n" "As armas\te\tos barões\n que",应返回["As","armas","e","os","barões","que"]
你的当前代码与错误分析
你写的代码是这样的:
sep :: Eq a => [a] -> [a] -> [[a]] sep _ [] = [] sep n (x:xs) | x `elem` n = " " ++ sep n xs | otherwise = x : sep n xs
报错的核心是类型不匹配:
- 分隔符分支的
" " ++ sep n xs:" "是[Char]类型,而sep n xs的返回值是[[a]](列表的列表),这俩根本没法用++拼接 - 非分隔符分支的
x : sep n xs:x是单个元素(类型a),但sep n xs是[[a]],:运算符要求左右两边类型统一(左边是元素,右边是同类型元素的列表),这里显然不匹配
正确的实现思路与代码
我们需要用一个辅助函数来维护当前正在构建的单词,遍历目标列表时逐步攒单词,遇到分隔符时把攒好的单词加入结果(如果有的话),最后处理末尾剩余的单词。
正确的代码如下:
sep :: Eq a => [a] -> [a] -> [[a]] sep delimiters = go [] where -- 遍历到末尾时,若还有未完成的单词就返回,否则返回空列表 go current [] = if null current then [] else [current] go current (x:xs) -- 遇到分隔符的情况 | x `elem` delimiters = if null current then go [] xs -- 没有正在构建的单词,直接跳过分隔符 else current : go [] xs -- 把当前单词加入结果,重置当前单词继续遍历 -- 遇到非分隔符的情况,把字符加入当前正在构建的单词 | otherwise = go (current ++ [x]) xs
代码解释
- 辅助函数
go的第一个参数current用来存储当前正在拼接的单词(初始为空列表) - 当遍历到目标列表末尾时,如果
current不为空,就把它作为最后一个元素返回,避免丢失最后一个单词 - 遇到分隔符时:如果当前没有正在构建的单词(比如连续多个分隔符),就直接跳过;如果有,就把这个单词加入结果列表,然后重置
current继续处理剩下的内容 - 遇到非分隔符字符时,把它追加到
current里,继续构建当前单词
测试一下你的示例输入:
sep " \t\n" "As armas\te\tos barões\n que" -- 输出:["As","armas","e","os","barões","que"]
完全符合你的需求!
内容的提问来源于stack exchange,提问作者Wireless
相关产品推荐
相关产品推荐

