晚上,
这是我在Haskell中等同于“str_replace”的尝试
strReplace :: (Char, Char) -> String -> String -> String {- Original (y) Parsed (z) -}
strReplace _ "" y = y
strReplace x y z = if (y !! 0) == fst x then strReplace x (drop 1 y) (z:([snd x])) else strReplace x (drop 1 y) (z:(y!!0))
基本上,第一个元组是被替换的字符(即('A','B')替换所有As到Bs,第二个参数是要解析的字符串,第三个参数应该总是留空string。编译器返回
*** Expression : z : [snd x]
*** Term : z
*** Type : [Char]
*** Does not match : Char
想法? :)
答案 0 :(得分:1)
您的代码存在的问题是z : [snd x]
不正确,z
是一个列表但:
希望它是一个元素。这可以使用z ++ [snd x]
修复。
如果看到签名类型有帮助
(:) :: a -> [a] -> [a]
(++) :: [a] -> [a] -> [a]
或在您的具体情况
(:) :: Char -> String -> String
(++) :: String -> String -> String
如果我建议对您的代码进行一些改进,那么首先strReplace
不应强制您传递空字符串
strReplace :: (Char, Char) -> String -> String
接下来,我们可以使用高阶函数或显式递归两种方式。
-- recursion
strReplace _ "" = "" -- Base case
strReplace (a, b) (c:cs) | a == c = b : strReplace (a,b) cs
| otherwise = c : strReplace (a, b) cs
所以这里如果字符串为空我们已经完成,否则我们模式匹配,如果第一个字符是要替换的字符,我们替换它并递归,否则我们不替换它并递归。
实际上可以使用map
strReplace (a, b) s = map (\c -> if c == a then b else c) s
这与我们以前的版本完全相同,但map
抽象出循环逻辑。
答案 1 :(得分:1)
z的类型为[Char]
。您无法使用:
将[Char]
纳入[Char]
- 请查看:
的类型签名。您必须使用++
将一个[Char]
附加到另一个。{/ p>
补充要点:
strReplace
签名:: Char -> Char -> String -> String -> String
。:: a -> a -> [a] -> [a] -> [a]
let
或where
)。foo x y = if (y == ... ) ... else ...
的函数,它几乎总能通过模式匹配或警卫来改进。要扩展第4点,您可以将第三行重写为
strReplace x y z | y !! 0 == fst x = ...
| otherwise = ...
更好的是,如果你在第1点接受我的建议并将元组拆分为两个简单的Char
参数,你可以这样做:
strReplace x1 x2 y@(y1:ys) z | x1 == y = ...
| otherwise = ...