Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将函数更改为在Haskell中使用递归_Haskell_Recursion - Fatal编程技术网

将函数更改为在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
分别工作。您还可以注意到,您的和我的执行两个不同的递归调用,这是可以避免的。还请注意,您应该区分两个
清理功能(全局/本地)。