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:
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:
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!
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)
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.
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
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.
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:
sanitize :: String -> String
sanitize [] = []
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.