用于将修改顺序应用于字符串的函数

tur*_*tle 3 haskell

我有一个函数,它接受一个子字符串和一个字符串,并在字符串中查找匹配的子字符串,并将匹配的字符更改为大写.例如:

> upperCase "aaa" "---aaa---"
"---AAA---"
Run Code Online (Sandbox Code Playgroud)

我想使用这个函数,但是使用几个子串应用upperCase操作.例如:

> upperCases ["aaa", "bbb", "c"] "d---aaa---c--bbb"
"d---AAA---C--BBB"
Run Code Online (Sandbox Code Playgroud)

我正在努力理解的是我如何做到这一点.这是我最好的尝试:

upperCases [] st = st
upperCases [x] st = upperCase x st
upperCases (x:xs) st = upperCases xs st
Run Code Online (Sandbox Code Playgroud)

当我upperCases在上面的例子中使用此函数时,我得到以下不正确的输出:

"d---aaa---C--bbb"
Run Code Online (Sandbox Code Playgroud)

只更改了最后一个子字符串.这个函数有什么问题,我可以编写一个函数来执行示例操作吗?

lef*_*out 6

你只是x从模式中"扔掉"了x:xs.显然,在递归到其他匹配之前,您需要先使用它!

upperCases (x:xs) st = upperCases xs $ upperCase x st
Run Code Online (Sandbox Code Playgroud)

但是,最好不要明确地写出递归.你想要的基本上是将一堆功能链接在一起.这是一个折叠:

chain :: [a -> a] -> a -> a
chain = foldr (.) id
Run Code Online (Sandbox Code Playgroud)

现在,目前你还没有功能a->a.相反,你有b->a->a,其中两个ba实际上String.但是你可以部分地应用第一个参数,例如

[upperCase "aaa", upperCase "bbb", upperCase "c"] :: [String -> String]
Run Code Online (Sandbox Code Playgroud)

更简洁的是,这个列表可以定义为map upperCase ["aaa", "bbb", "c"].

总而言之,你需要

upperCases = foldr (.) id . map upperCase
Run Code Online (Sandbox Code Playgroud)

实际上,你甚至可以包括upperCase在折叠中:

upperCases = foldr ((.) . upperCase) id
Run Code Online (Sandbox Code Playgroud)