Skip to content

递归模式

Functional languages excel at wholemeal programming, a term coined by Geraint Jones. Wholemeal programming means to think big: work with an entire list, rather than a sequence of elements; develop a solution space, rather than an individual solution; imagine a graph, rather than a single path. The wholemeal approach often offers new insights or provides new perspectives on a given problem. It is nicely complemented by the idea of projective programming: first solve a more general problem, then extract the interesting bits and pieces by transforming the general program into more specialised ones.

全麦编程/整体编程 强调要从整体上看问题。

在haskell这样一门函数式编程语言中, 递归是非常常用和重要的操作。

而大部分都递归操作其实是存在一些共性的, 尤其是对于列表:

  • 对列表每个元素进行一些操作, 得到新列表
  • 去除不满足条件的一些元素
  • 由列表计算值
  • 生成一个列表

如去除不满足条件的一些元素, 本质上是对列表进行一次遍历, 并对每个元素应用一段逻辑来决定是否要去除, 最后得到新的一个列表。

具体的判断逻辑我们并不在意, 重要的是递归遍历 + 逻辑判断这个相同的"递归逻辑", 我们叫他递归模式。

根据我们学过的知识, 很容易就能写出这样的代码:

haskell
filterIntList :: (Int -> Bool) -> [Int] -> [Int]
filterIntList f [] = []
filterIntList f (x:xs)
  | f x = x : filterIntList f xs
  | otherwise = filterIntList f xs

封装/抽取递归模式, 使得我们只需要编写具体的业务逻辑即可, 屏蔽了大量没必要的关注点。

泛型

haskell
filterIntList :: (Int -> Bool) -> [Int] -> [Int]
filterIntList f [] = []
filterIntList f (x:xs)
  | f x = x : filterIntList f xs
  | otherwise = filterIntList f xs

这个函数还不错, 但它只能用在[Int]类型上。

如果要进一步提升它的抽象程度, 就需要使用泛型, 让它能适配于任何类型的列表。

类型上的泛型

在自定义类型上使用泛型, 只需要将泛型符号加到类型名后即可。

如一个列表类型:

haskell
data List e = EMPTY | CONS e (List e)
  • EMPTY, 空参构造函数, 表示列表的结束
  • CONS, 列表的结点
    • e: 结点存储的数据
    • (LIST e): 下一个结点

其中e叫做类型变量, 它代表了一个不确定的类型, 需要由使用时指定或推断。

使用具有泛型的类型也很简单, 就像为一个函数传参一样:

haskell
lst1 :: List Int
lst1 = CONS 3 (CONS 2 EMPTY)

请注意, 类型变量必须以小写字母开头, 而类型以大写字母开头

函数上的泛型

很简单 ,直接在函数类型定义上使用类型变量即可。

haskell
myFilter :: (e -> Bool) -> [e] -> [e]
myFilter f [] = []
myFilter f (x : xs)
  | f x = x : myFilter f xs
  | otherwise = myFilter f xs

main = do
  print (myFilter (> 3) [1, 2, 3, 4, 5])

Prelude

Prelude是haskell的标准库, 它是默认导入, 因此不需要进行任何导入即可使用它。

prelude中有非常非常多的实用函数!像mapfilterfoldl等等。