简体   繁体   English

在Haskell中更改函数以使用递归

[英]change the function to use recursion in Haskell

I am writing a function that can take a string that contains spaces to produce the output such as this: "http://cs.edu/my space/.html" == "http://cs.edu/my%20space/.html" I successfully have it using concat, but I want it with recursion now this is what I came up with until now: 我正在编写一个函数,该函数可以采用包含空格的字符串来产生如下输出: "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

I can not figured out how to use guard efficiently here, or something else appropriate that working fine. 我无法弄清楚如何在这里有效地使用警卫,或者其他可以正常工作的适当方法。 Obviously, I am not using recursion effectively as above code, I need a help to reform it using recursion and with the appropriate type signature for my function changer. 显然,我没有像上述代码那样有效地使用递归,我需要帮助来使用递归并为我的函数转换器使用适当的类型签名来对其进行重新构造。

The following is my other code i tried to recursive the main function changer instead of using go the helper: 以下是我尝试递归主函数更改器而不是使用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" 

It is complaining about y " Not in scope: `y'" Thanks a lot! 它在抱怨y“不在范围内:” y“”非常感谢!

In fact, you're trying to make it more complicated than it needs to be : 实际上,您正在尝试使其变得比所需的更为复杂:

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"

(You were trying to test many more cases than necessary and, as David Young said, you were using an intermediate function) (您正在尝试测试比必要更多的案例,并且正如David Young所说,您正在使用中间函数)

It also seems you're confusing pattern matching and guards. 似乎您也混淆了模式匹配和防护。 What you need here is pattern matching. 您需要的是模式匹配。 Guards are about predicates which evaluate to True or False. 警戒是关于谓词,其结果为True或False。

If you really want to write it with guards, it should look like this 如果您真的想用警卫来写它,它应该看起来像这样

sanitize :: String -> String
sanitize xs
   | xs == []       = []
   | head xs == ' ' = "%20" ++ sanitize (tail xs)
   | otherwise      = head xs:sanitize (tail xs)

While the style that @zigazou has shown is perfectly acceptable and correct, I would prefer avoiding explicit recursion and factor out the conversion function like 虽然@zigazou展示的样式是完全可以接受和正确的,但我还是希望避免显式递归并排除转换函数,例如

urlEncodeChar :: Char -> String
urlEncodeChar ' ' = "%20"
urlEncodeChar '%' = "%25"
urlEncodeChar x   = [x]

changer :: String -> String
changer = concatMap urlEncodeChar

Doing it this way means that you have a much simpler function to edit when you need to add a new mapping, the pattern matching is much more clear, and then you let concatMap handle joining all those values together efficiently. 这样做意味着您需要添加新映射时具有更简单的功能来编辑,模式匹配更加清晰,然后让concatMap有效地将所有这些值结合在一起。

I really do not know which one the best beside that you both guys correct and appreciated your answers. 我真的不知道你们中的哪一个最正确,除了你们俩都正确并赞赏您的回答。 I have solved it after David Young discussion and help as below: 经过David Young的讨论和帮助,我已经解决了以下问题:

sanitize :: String -> String 清理::字符串->字符串

sanitize [] = [] 消毒[] = []

sanitize (x:xs) = sanitize x xs 清理(​​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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM