我很难理解如何以递归方式思考问题,并使用Haskell解决它们.我花了几个小时阅读试图绕过递归.我经常从理解它的人那里得到的解释从来都不清楚,就像"你传递一个函数,函数的名称作为参数,函数将执行,解决一小部分问题并调用一次又一次地起作用,直到你击中基础案例".
有人可以请你好心,并引导我完成这三个简单的递归函数的思考过程吗?与其说是功能不是很多,而是代码如何以递归方式执行并解决问题.
提前谢谢了!
功能1
maximum' [] = error "maximum of empty list"
maximum' [x] = x
maximum' (x:rest) = max x(maximum' rest)
Run Code Online (Sandbox Code Playgroud)
功能2
take' n _
| n <= 0 = []
take' _ [] = []
take' n (x:xs) = x : take' (n-1) xs
Run Code Online (Sandbox Code Playgroud)
功能3
reverse' [] = []
reverse' (x:xs) = reverse' xs ++ [x]
Run Code Online (Sandbox Code Playgroud)
Chr*_*ett 19
在尝试理解递归时,您可能会发现更容易思考算法对给定输入的行为方式.很容易挂断执行路径的样子,所以请问自己这样的问题:
或者,对于数字的递归:
递归算法的结构通常只是覆盖上述情况的问题.因此,让我们看看您的算法如何表现以了解这种方法:
maximum [] = error
maximum [1] = 1
maximum [1, 2] = 2
Run Code Online (Sandbox Code Playgroud)
如您所见,唯一有趣的行为是#3.其他人只是确保算法终止.看看定义,
maximum' (x:rest) = max x (maximum' rest)
Run Code Online (Sandbox Code Playgroud)
调用此[1, 2]扩展为:
maximum [1, 2] ~ max 1 (maximum' [2])
~ max 1 2
Run Code Online (Sandbox Code Playgroud)
maximum'通过返回一个数字来工作,这种情况下知道如何使用递归处理max.让我们再看一个案例:
maximum [0, 1, 2] ~ max 0 (maximum' [1, 2])
~ max 0 (max 1 2)
~ max 0 2
Run Code Online (Sandbox Code Playgroud)
您可以看到,对于此输入,maximum'第一行中的递归调用与前一示例完全相同.
reverse [] = []
reverse [1] = [1]
reverse [1, 2] = [2, 1]
Run Code Online (Sandbox Code Playgroud)
通过取得给定列表的头部并在最后粘贴它来反向工作.对于一个空列表,这不涉及任何工作,因此这是基本情况.所以给定定义:
reverse' (x:xs) = reverse' xs ++ [x]
Run Code Online (Sandbox Code Playgroud)
我们做一些替代.鉴于[x]相当于x:[],您可以看到实际上有两个值要处理:
reverse' [1] ~ reverse' [] ++ 1
~ [] ++ 1
~ [1]
Run Code Online (Sandbox Code Playgroud)
很容易.对于两元素列表:
reverse' [0, 1] ~ reverse' [1] ++ 0
~ [] ++ [1] ++ 0
~ [1, 0]
Run Code Online (Sandbox Code Playgroud)
此函数引入了整数参数和列表的递归,因此有两种基本情况.
如果我们采取0或更少的项目会发生什么?我们不需要任何物品,所以只需返回空列表即可.
take' n _ | n <= 0 = []
take' -1 [1] = []
take' 0 [1] = []
Run Code Online (Sandbox Code Playgroud)如果我们传递一个空列表会怎么样?没有更多的项目,所以停止递归.
take' _ [] = []
take' 1 [] = []
take -1 [] = []
Run Code Online (Sandbox Code Playgroud)算法的核心实际上是沿着列表向下移动,拉开输入列表并减少要采用的项目数,直到上述任一基本情况停止进程.
take' n (x:xs) = x : take' (n-1) xs
Run Code Online (Sandbox Code Playgroud)
因此,在首先满足数字基本情况的情况下,我们在到达列表末尾之前停止.
take' 1 [9, 8] ~ 9 : take (1-1) [8]
~ 9 : take 0 [8]
~ 9 : []
~ [9]
Run Code Online (Sandbox Code Playgroud)
在首先满足列表基本情况的情况下,我们在计数器达到0之前耗尽项目,并且只返回我们能够做的事情.
take' 3 [9, 8] ~ 9 : take (3-1) [8]
~ 9 : take 2 [8]
~ 9 : 8 : take 1 []
~ 9 : 8 : []
~ [9, 8]
Run Code Online (Sandbox Code Playgroud)