我正在编写一个函数,可以使用包含空格的字符串来生成输出,例如:"http://cs.edu/my space/.html" == "http://cs.edu/my%20space/.html"
我成功地使用了concat,但我现在想要递归,这是我现在想出的:
changer [] = []
changer (x:xs) = go x xs
where go ' ' [] = "%20"
go y [] = [y]
go ' ' (x:xs) = '%':'2':'0': go x xs
go y (x:xs) = y: go x xs
我无法弄清楚如何在这里有效地使用防护,或其他合适的工作正常。显然,我没有像上面的代码那样有效地使用递归,我需要帮助来使用递归和我的函数转换器的相应类型签名来改进它。
以下是我的其他代码我试图递归主函数更换器而不是使用go帮助器:
sanitize [] = []
sanitize (x:xs)
|sanitize x xs = sanitize xs
|sanitize y [] = [y]
|sanitize ' ' (x:xs) = '%':'2':'0': go x xs
|sanitize y (x:xs) = y: go x xs
where go ' ' [] = "%20"
抱怨y“不在范围内:'y'” 非常感谢!
答案 0 :(得分:3)
事实上,你正试图让它变得更加复杂:
module Main where
changer :: String -> String
changer [] = []
changer (' ':xs) = "%20" ++ changer xs
changer (x:xs) = x:changer xs
main = do
print $ changer "http://cs.edu/my space.html"
(你试图测试更多不必要的案例,正如David Young所说,你使用的是中间函数)
你似乎也混淆了模式匹配和守卫。你需要的是模式匹配。守卫是关于判断为真或假的谓词。
如果你真的想用守卫写它,它应该看起来像这样
sanitize :: String -> String
sanitize xs
| xs == [] = []
| head xs == ' ' = "%20" ++ sanitize (tail xs)
| otherwise = head xs:sanitize (tail xs)
答案 1 :(得分:1)
虽然@zigazou所展示的风格是完全可以接受和正确的,但我宁愿避免显式递归并将转换函数分解为
urlEncodeChar :: Char -> String
urlEncodeChar ' ' = "%20"
urlEncodeChar '%' = "%25"
urlEncodeChar x = [x]
changer :: String -> String
changer = concatMap urlEncodeChar
这样做意味着当您需要添加新映射时,您可以使用更简单的函数进行编辑,模式匹配更加清晰,然后您让concatMap
处理所有这些值有效地连接在一起
答案 2 :(得分:0)
我真的不知道哪一个最好,除了你们两个人都正确并感谢你们的答案。 我在David Young的讨论和帮助后解决了这个问题,如下所示:
sanitize :: String - >串
清理[] = []
sanitize(x:xs)= sanitize x xs
where sanitize ' ' [] = "%20"
sanitize y [] = [y]
sanitize ' ' (x:xs) = '%':'2':'0': sanitize x xs
sanitize y (x:xs) = y: sanitize x xs