Haskell使用foldl实现字符替换为剩余长度的匿名函数问题
实现要求
你需要借助foldl编写符合如下签名的Haskell函数:
- 入参为字符串
str,返回值为一个匿名函数 - 返回的匿名函数接收单个字符参数
c,将原字符串str中所有与c相等的字符,替换为该字符所在位置之后剩余字符的数量(转成字符串形式)
函数签名:
speak :: String -> (Char -> String)
运行示例:
speak "Hello" 'e'输出"H3llo":字符'e'位于索引1位(从0开始计数),后方剩余3个字符,因此替换为"3"speak "gate" 't'输出"ga1e":字符't'位于索引2位,后方剩余1个字符,因此替换为"1"
原代码错误点
你提交的错误代码如下:
speak :: String -> (Char ->String) speak str = foldl (\x -> if x == str then x = show(length str) else str) str
存在4个核心问题:
- 返回值不符合签名要求:直接返回了
foldl的计算结果,没有定义接收字符c的匿名函数 foldl入参不符合语法:foldl要求接收的折叠函数带2个参数(累加器、当前遍历元素),你写的lambda仅接收1个参数- 语法非法:Haskell是纯函数式语言,不存在命令式赋值操作
x = ... - 逻辑完全缺失:没有逐字符遍历判断匹配,也没有记录每个位置对应的后方剩余字符数,替换逻辑不成立
基于foldl的正确实现
实现思路:遍历字符串时用二元组作为累加器,同时维护「已构建的结果字符串」和「当前位置后方的剩余字符数」两个状态,每遍历一个字符就更新状态,遍历完成后取累加器中的结果字符串即可。
speak :: String -> (Char -> String) speak str = \c -> fst $ foldl processChar ("", length str - 1) str where processChar (acc, remainLen) currChar | currChar == c = (acc ++ show remainLen, remainLen - 1) | otherwise = (acc ++ [currChar], remainLen - 1)
代码逻辑说明:
speak str直接返回接收字符c的匿名函数,匹配函数签名要求- 折叠初始值:初始结果为空串,第一个遍历字符(索引0)后方的剩余字符数为
length str - 1 - 每一步遍历的处理规则:
- 如果当前字符和待替换字符
c相等,就把当前剩余长度转成字符串追加到结果末尾 - 如果不相等,就把原字符直接追加到结果末尾
- 无论是否匹配,下一步的剩余长度减1
- 如果当前字符和待替换字符
- 折叠完成后取累加器二元组的第一个元素,就是最终替换完成的字符串
该实现可以直接通过给出的两个示例测试。
内容的提问来源于stack exchange,提问作者Rado
相关产品推荐
相关产品推荐

