替换haskell中的单词

替换haskell中的单词,haskell,str-replace,Haskell,Str Replace,我想替换全文。类型定义为: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"` 它应该带有虚词和unwords 你知道吗 对于现代Haskell中的文本操作,通常建议不

我想替换全文。类型定义为: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"`
它应该带有虚词和unwords


你知道吗

对于现代Haskell中的文本操作,通常建议不要使用字符串类型,而是使用包。如果出于某种原因,以字符串开头,可以使用将其转换为文本。然后,使用允许您执行以下操作的功能:

>>> :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"
理解作业 你的作业要求你使用单词和单词:

因此,很明显,您需要对字符串列表进行操作:

innerFunc :: [String] -> [String]
这将使您能够使用UNWORD。innerFunc。话。但是,这看起来就像使用正确的替换函数映射字符串:

innerFunc = map f
其中f应该是

f :: String -> String
因此,如果您能够创建一个函数来正确替换单个单词,就足够了

解决作业 如上所述,我们现在正在寻找一个能够正确替换单个单词的函数。为了方便起见,让我们创建一个类型同义词*,这样我们就知道它当前是指单个单词还是整个句子

*注意,Haskell已经在Data.Word中提供了Word,但这是完全不同的,即无符号Int变量,因此在下面的代码中只是为了方便起见

用单个替换模式替换单个单词 让我们从非常简单的开始。我们将编写一个只适用于单个单词的函数:

replaceSimple :: (Word, Word) -> Word -> Word
replaceSimple (orig, repl) word = if orig == word then repl else word
很明显,这将替换单词iff orig==单词:

用许多替换模式替换单个单词 现在,我们想将这些知识用于仍然在单个单词上运行的函数,但从列表中获取替换项并应用第一个匹配项:

replaceSingle :: [(Word, Word)] -> Word -> Word
replaceSingle []     word = word
replaceSingle (r:rs) word = if word == fst r then snd r else replaceMany rs word
仔细观察:如果替换列表为空,或者在任何其他替换之前有一个相同的替换,如fox、fox,则replaceSSingle将保持单词不变。否则,如果替换项匹配,它将与替换项交换单词,或者尝试其他替换规则

拼凑 现在看起来就像上面的f,不是吗?的确如此!您只需提供替换列表:

:t replaceSingle [("fox","cat"),("he","she")]
replaceSingle [("fox","cat"),("he","she")] :: String -> String
您所需要做的就是按照上面所写的映射此函数


将函数映射、replaceSignle、unwords和words放在一起作为练习留给读者。

Have?如果是这样的话,你有什么问题,你在哪里被卡住了?我不知道在我使用虚词后如何将单词保存到某个东西中。他不是停留在原始签名上,而是停留在单词和未单词上。@Zeta,好吧,我不明白使用单词和未单词是一项要求,我把它当作误导性的暗示。我很难想象有这样一个限制的真实场景。也许如果你不想依赖文本,但即使如此,也可能不需要使用单词或非单词。@Dannynynavarro:作为一种语言的新手,可能在Monoid、Foldable、Monad和Arrow方面有困难。尽管效率不高,但理解UNWORD很简单。映射我的替换。文字,比解包简单得多。附录。。。。这就是作业和约束的意义所在——一步一步地学习一门语言。@Zeta,我的看法不同。如果一个新来的人用unwords来代替Endo,我同意你的看法,没关系。我甚至认为给出关于单词和单词的提示是可以的,但是把它作为一个要求会使它对于真实的案例场景来说过于人为。在现实生活中,受类型签名约束比受某些人告诉您必须使用的函数约束要频繁得多。非常感谢您提供了详尽的答案!
replaceSimple ("fox", "cat") "fox" == "cat"
replaceSimple ("fox", "cat") "dog" == "dog"
replaceSingle :: [(Word, Word)] -> Word -> Word
replaceSingle []     word = word
replaceSingle (r:rs) word = if word == fst r then snd r else replaceMany rs word
:t replaceSingle [("fox","cat"),("he","she")]
replaceSingle [("fox","cat"),("he","she")] :: String -> String