[英]change the function to use recursion in Haskell
我正在编写一个函数,该函数可以采用包含空格的字符串来产生如下输出: "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“”非常感谢!
实际上,您正在尝试使其变得比所需的更为复杂:
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所说,您正在使用中间函数)
似乎您也混淆了模式匹配和防护。 您需要的是模式匹配。 警戒是关于谓词,其结果为True或False。
如果您真的想用警卫来写它,它应该看起来像这样
sanitize :: String -> String
sanitize xs
| xs == [] = []
| head xs == ' ' = "%20" ++ sanitize (tail xs)
| otherwise = head xs:sanitize (tail xs)
虽然@zigazou展示的样式是完全可以接受和正确的,但我还是希望避免显式递归并排除转换函数,例如
urlEncodeChar :: Char -> String
urlEncodeChar ' ' = "%20"
urlEncodeChar '%' = "%25"
urlEncodeChar x = [x]
changer :: String -> String
changer = concatMap urlEncodeChar
这样做意味着您需要添加新映射时具有更简单的功能来编辑,模式匹配更加清晰,然后让concatMap
有效地将所有这些值结合在一起。
我真的不知道你们中的哪一个最正确,除了你们俩都正确并赞赏您的回答。 经过David Young的讨论和帮助,我已经解决了以下问题:
清理::字符串->字符串
消毒[] = []
清理(x:xs)=清理x xs
where sanitize ' ' [] = "%20"
sanitize y [] = [y]
sanitize ' ' (x:xs) = '%':'2':'0': sanitize x xs
sanitize y (x:xs) = y: sanitize x xs
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.