将函数更改为在Haskell中使用递归
我正在编写一个函数,它可以接受包含空格的字符串来生成如下输出:将函数更改为在Haskell中使用递归,haskell,recursion,Haskell,Recursion,我正在编写一个函数,它可以接受包含空格的字符串来生成如下输出:“http://cs.edu/my 空格/.html“==”http://cs.edu/my%20space/.html“ 我使用concat成功地实现了它,但我现在希望它与递归结合,这是我到目前为止的想法: changer [] = [] changer (x:xs) = go x xs where go ' ' [] = "%20" go y
“http://cs.edu/my 空格/.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
我不知道如何在这里有效地使用guard,或者其他合适的工作方式。显然,我并没有像上面的代码那样有效地使用递归,我需要一个帮助来使用递归对其进行改造,并为我的函数转换器提供适当的类型签名
以下是我的另一段代码,我尝试递归主函数转换器,而不是使用go The helper:
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所说,您使用的是一个中间函数)
你似乎也混淆了模式匹配和防护。这里需要的是模式匹配。Guards是关于计算结果为True或False的谓词的
如果你真的想用警卫来写,它应该是这样的
sanitize :: String -> String
sanitize xs
| xs == [] = []
| head xs == ' ' = "%20" ++ sanitize (tail xs)
| otherwise = head xs:sanitize (tail xs)
事实上,你正试图让它变得比需要的更复杂:
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所说,您使用的是一个中间函数)
你似乎也混淆了模式匹配和防护。这里需要的是模式匹配。Guards是关于计算结果为True或False的谓词的
如果你真的想用警卫来写,它应该是这样的
sanitize :: String -> String
sanitize xs
| xs == [] = []
| head xs == ' ' = "%20" ++ sanitize (tail xs)
| otherwise = head xs:sanitize (tail xs)
尽管@zigazu所展示的样式是完全可以接受和正确的,但我更愿意避免显式递归,并像下面那样考虑转换函数
urlEncodeChar :: Char -> String
urlEncodeChar ' ' = "%20"
urlEncodeChar '%' = "%25"
urlEncodeChar x = [x]
changer :: String -> String
changer = concatMap urlEncodeChar
这样做意味着当你需要添加一个新的映射时,你有一个简单得多的函数可以编辑,模式匹配更加清晰,然后你可以让
concatMap
有效地将所有这些值连接在一起。尽管@zigazu显示的样式是完全可以接受和正确的,我更喜欢避免显式递归,并像
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
我真的不知道哪一个是最好的,除了你们两个都正确和感谢你们的答案。 经过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
我不太明白。这段代码是递归的,你的例子看起来很有效。是的,这是真的,但我想递归函数转换器,而不是使用go助手。或者你认为它仍然被称为递归??当然,它仍然被称为递归。好吧,它现在肯定是递归的。执行一个附加步骤,然后立即对算法的其余部分使用递归函数,因此它本质上是递归的。如果你真的想知道这个问题的答案,你应该发布给出错误和错误的代码。没问题!您正在尝试使用类似于模式匹配的保护。你应该像你最初使用
go
一样使用sanitize
进行模式匹配(你不需要任何|
s)。我不确定我是否理解。这段代码是递归的,你的例子看起来很有效。是的,这是真的,但我想递归函数转换器,而不是使用go助手。或者你认为它仍然被称为递归??当然,它仍然被称为递归。好吧,它现在肯定是递归的。执行一个附加步骤,然后立即对算法的其余部分使用递归函数,因此它本质上是递归的。如果你真的想知道这个问题的答案,你应该发布给出错误和错误的代码。没问题!您正在尝试使用类似于模式匹配的保护。你应该像你最初使用go
一样使用sanitize
进行模式匹配(你不需要任何|
s)。我的代码只是一个学校解决方案,函数在没有任何其他函数帮助的情况下执行所有操作。bheklillr版本更好,因为它遵循单一责任原则,使urlEncodeChar
和changer
分别工作。您还可以注意到,您的和我的执行两个不同的递归调用,这是可以避免的。还要注意的是,您应该区分两个清理函数(全局/本地)。我的代码只是一个学校解决方案,该函数在没有任何其他函数帮助的情况下执行所有操作。bheklillr版本更好,因为它遵循单一责任原则,使urlEncodeChar
和changer
分别工作。您还可以注意到,您的和我的执行两个不同的递归调用,这是可以避免的。还请注意,您应该区分两个清理功能(全局/本地)。