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

时间:2014-11-03 05:02:03

标签: haskell recursion

我正在编写一个函数,可以使用包含空格的字符串来生成输出,例如:"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'” 非常感谢!

3 个答案:

答案 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