任意循环结构都可以转化为递归,这就是haskell没有for while也可以实现任何应用的原因。
有些问题可以很容易的看出递归形式(如归并排序,快速排序),不过有的问题却不太容易(例如查找一组数中的最大值,统计数组的长度)。训练将任意问题都看成递归形式的能力,可以帮助我们更好的写出haskell代码,甚至是脱离了haskell之后,也可以使我们解决问题时多了一件工具。更好的理解一些比较复杂的算法(非常多的算法都是递归形式)。
以递归的观点看问题,就要将一个问题化解成一系列相似的小问题,同时要考虑到触底情况,递归的触底就是在某个限制条件触发时,递归函数不继续调用而直接返回,否则递归就会一直运行下去,直到爆栈为止。
haskell因为有模式匹配以及guards的存在,递归写法和一般语言不太一样,一开始会比较难理解语法。
求list的最大值
maximum' [] = error "maximum of empty list"
maximum' [x] = x
maximum' (x:xs)
| x > maxTail = x
| otherwise = maxTail
where maxTail = maximum' xs
--等价的ruby常规写法
def max(arr)
min=arr[0]
arr.each do |item|
if item>min
min=item
end
end
min
end
--等价的ruby递归写法
def max2(arr)
#求arr[0~arr.length]的最大值,然后和arr[arr.length-1]比较
_max2(arr,arr.length)
end
def _max2(arr, length)
if length == 1
return arr[0]
end
max=_max2(arr,length-1)
if max>arr[length-1]
return max
else
return arr[length-1]
end
end
--可以看出,haskell即使是对比以简洁著称的ruby,他的递归代码量也非常少,所以他的语法结构是十分适合写递归函数的。
replicate 函数, 它取一个 Int 值和一个元素做参数, 返回一个包
含多个重复元素的 List, 如 replicate 3 5 返回 [5,5,5]
replicate' n x
| n <= 0 = []
| otherwise = x:replicate' (n-1) x
take 函数, 它可以从一个 List 取出一定数量的元素. 如
take 3 [5,4,3,2,1], 得 [5,4,3],注意他有两个触底情况
take' n _
| n <= 0 = []
take' _ [] = []
take' n (x:xs) = x : take' (n-1) xs
reverse 函数简单地反转一个 List
reverse' [] = []
reverse' (x:xs) = reverse' xs ++ [x]
查找
contain' a [] = False
contain' a (x:xs)
| a == x = True
| otherwise = contain' a xs
快速排序(因为列表描述法的存在代码短的不可思议)
(不过这个需要额外的空间貌似,常规的快排是直接在单个数组的swap的,他这个是先分两个再合并)
quicksort [] = []
quicksort (x:xs) =
let smallerSorted = quicksort [a | a <- xs, a <= x]
biggerSorted = quicksort [a | a <- xs, a > x]
in smallerSorted ++ [x] ++ biggerSorted
欢迎关注我的github
https://github.com/luckyCatMiao