Haskell递归函数titleRec问题:处理标题大小写漏第二个单词
问题原因分析
你的adjust函数存在逻辑错误,直接导致第二个单词被跳过:
adjust (y:ys) = [if (length y >= 4) then capitalisedRec y else capitilized2 y | y<- ys]
这里的核心问题有两点:
- 参数
y被完全忽略:函数参数里的y(也就是原列表中首词之后的第一个单词,比如测试用例里的"bOSun")没有被处理,直接被丢弃。 - 列表推导式遍历范围错误:推导式里遍历的是
ys(即y之后的剩余单词),只处理了从第三个单词开始的内容,完全跳过了第二个单词。
举个具体例子,当adjust接收["bOSun", "ANd", "thE", "BriDGe"]时:
- 参数
y是"bOSun",ys是["ANd", "thE", "BriDGe"] - 列表推导式仅遍历
ys处理后三个单词,"bOSun"直接丢失,所以最终结果里没有它的处理结果。
修复方案
你可以把adjust改成递归处理每个单词,或者用map简化逻辑,两种方式都能解决问题:
方案1:递归实现adjust
adjust [] = [] adjust (y:ys) = (if length y >=4 then capitalisedRec y else capitilized2 y) : adjust ys
方案2:用map简化(更简洁)
adjust本质是对每个单词应用统一的判断规则,用map可以替代递归,代码更清晰:
titleRec :: [String] -> [String] titleRec [] = [] titleRec (x:xs) = capitalisedRec x : map adjustWord xs where adjustWord word = if length word >=4 then capitalisedRec word else capitilized2 word
另外,你的capitilized2函数可以简化为map toLower,没必要写列表推导式:
capitilized2 :: String -> String capitilized2 = map toLower
修复后的完整代码
import Data.Char (toUpper, toLower) capitalisedRec :: String -> String capitalisedRec [] = [] capitalisedRec (x:xs) = toUpper x : lowered xs where lowered [] = [] lowered (x:xs) = toLower x : lowered xs capitilized2 :: String -> String capitilized2 = map toLower titleRec :: [String] -> [String] titleRec [] = [] titleRec (x:xs) = capitalisedRec x : map adjustWord xs where adjustWord word = if length word >= 4 then capitalisedRec word else capitilized2 word
测试修复后的函数:
titleRec ["tHe", "bOSun", "ANd", "thE", "BriDGe"] -- 输出结果:["The","Bosun","and","the","Bridge"]
内容的提问来源于stack exchange,提问作者Ege Gülce
相关产品推荐
相关产品推荐

