我想替换文字中的完整单词。类型定义为:replace :: [(String, String)] -> String -> String
。功能示例是:
replace [("fox", "cat"), ("he", "she")] "The quick brown fox jumps over the lazy dog"
-- result: "The quick brown cat jumps over the lazy dog"`
应该是函数words
和unwords
。
答案 0 :(得分:3)
您的作业说明您应该使用words
和unwords
:
words :: String -> [String]
unwords :: [String] -> String
很明显,你需要在字符串列表上操作:
innerFunc :: [String] -> [String]
这样您就可以使用unwords . innerFunc . words
。但是,这看起来就像使用正确的替换函数映射字符串一样:
innerFunc = map f
其中f
应该是
f :: String -> String
如果你设法创建一个正确替换单个单词的功能就足够了。
如上所述,我们现在正在寻找一种能够正确替换单个单词的功能。为方便起见,我们创建一个类型同义词Word
*,因此我们知道这当前是针对单个单词还是整个句子。
*请注意,Haskell已经在Word
中提供Data.Word
,但这是完全不同的,即无符号Int
变体,所以它只是为了方便以下代码功能
type Word = String
让我们开始很简单。我们将编写一个仅适用于单个单词的函数:
replaceSimple :: (Word, Word) -> Word -> Word
replaceSimple (orig, repl) word = if orig == word then repl else word
很明显,这会取代word
iff orig == word
:
replaceSimple ("fox", "cat") "fox" == "cat"
replaceSimple ("fox", "cat") "dog" == "dog"
现在我们想要将这些知识用于仍在单个Word上运行的函数,但是从列表中取代它并应用匹配的第一个:
replaceSingle :: [(Word, Word)] -> Word -> Word
replaceSingle [] word = word
replaceSingle (r:rs) word = if word == fst r then snd r else replaceMany rs word
仔细观察:replaceSingle
如果替换列表为空,或者在任何其他替换之前存在像("fox","fox")
这样的身份替换,则保留该字不变。否则,如果他们匹配或尝试其余的替换规则,它将与替换人员交换word
。
现在replaceSingle
几乎看起来像f
,不是吗?它肯定是!您需要提供的只是替换列表:
:t replaceSingle [("fox","cat"),("he","she")]
replaceSingle [("fox","cat"),("he","she")] :: String -> String
您需要做的就是map
此功能如上所述。
将功能map
,replaceSingle
,unwords
和words
放在一起作为练习留给读者。
答案 1 :(得分:1)
对于现代Haskell中的文本操作,通常建议不要使用String
类型,而是使用text
包。如果由于某种原因您开始使用String
,则可以使用pack
将其转换为Text
。然后,使用replace
函数,您可以执行以下操作:
>>> :set -XOverloadedStrings
>>> import Data.Text
>>> replace "he" "she" . replace "fox" "cat" $ "The quick brown fox jumps over the lazy dog"
"Tshe quick brown cat jumps over tshe lazy dog"
如果由于某种原因你坚持使用原始类型签名,这是实现它的一种方法:
>>> import Data.Monoid
>>> import Data.Foldable
>>> import Control.Monad
>>> import Control.Arrow
>>> let replace' l = unpack . appEndo (foldMap (Endo . uncurry replace . join (***) pack) l) . pack
>>> :t replace'
replace' :: Foldable t => t (String, String) -> String -> String
>>> replace' [("he","she"), ("fox","cat")] "The quick brown fox jumps over the lazy dog"
"Tshe quick brown cat jumps over tshe lazy dog"