###### nklofy的专栏

factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial (n-1)

下面是元组和列表的模式匹配。函数调用时按照元组和列表的形式选择合适的模式。

addX :: (Double, Double) -> (Double, Double) -> Double
addX (x1, _) (x2, _) = x1 + y1
length' :: [a] -> Int
length' [] = 0
length' (x:[]) = 1
length' (x:xs) = 1 + length' xs

下面是定义函数的一些特殊形式，包括哨位（guard）、where、let、case。guard可以使函数在满足不同条件时得到不同的值，这些条件以“|”区分。case类似，实际上case就是模式匹配。where和let是函数定义时局部作用域中绑定变量或者函数。

max' :: (Ord a) => a -> a -> a
max' a b
| a < = b
| otherwise = a
addF :: [a] -> [a] -> a
addF s1 s2 = f1 + f2
where (f1:_) = s1
(f2:_) = s2
areaC :: Double -> Double
areaC x =
let square = x * x
in pi * square
find' :: [(Double, Double)] -> [Double]
find' xs = [xsi | (x1, x2) <- xs, let xsi = x1 * x2, xsi < 100]
head' :: [a] -> a
head' xs = case xs of [] -> error "empty"
(x:_) -> x

下面的例子是定义快速排序函数。

quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let small = [a | a <- xs, a <= x]
large = [a | a<- xs, a> x]
in quicksort small ++ [x] ++ quicksort large
高阶函数是函数式编程必不可少的特性。跟scheme一样，最常用的就是map、filter、foldr、foldl等。它们将集合视为整体，强调的是对集合的整体操作，而屏蔽了循环迭代等在数据结构的微观层面上的操作。

map :: (a -> b) -> [a] -> [b]
map _ [] =[]
map f (x:xs) = f x : map f fs
filter :: (a -> bool) -> [a] -> [a]
filter _ [] = []
filter p (x:xs)
| p x       = x : filter p xs
| otherwise = filter p xs
foldl :: (a -> b -> b) -> b -> [a] -> b
foldl f b0 [] = b0
foldl f b0 (x:xs) = foldl f (f x b0) xs
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f b0 [] = b0
foldr f b0 (x:xs) = f x (foldr f b0 xs)  
haskell有一些特殊形式可以简化函数的表达。例如$符号，其实就是改变左结合的函数调用为右结合。 ($) :: (a -> b) -> a -> b
f $x = f x sum (filter (> 10) (map (*2) [1..10])) sum$ filter (> 10) $map (*2) [1..10] 这两个表达式是等效的。另外还有一种重要的符号“.”表示函数组合。简洁的表达了将一个函数调用后的值传递给另一个函数作为参数。 (.) :: (b -> c) -> (a -> b) -> (a -> c) f . g = \x -> f (g x) replicate 2 (product (map (*3) (zipWith max [1,2] [4,5]))) replicate 2 . product . map (*3)$ zipWith max [1,2] [4,5]

最后举个例子来说明point-free风格。

sum' :: (Num a) => [a] -> a
sum' xs = foldl (+) 0 xs
sum' = foldl (+) 0

2017-12-28 11:29:56

2013-07-15 23:17:10

2016-02-22 01:15:53

2014-06-15 19:24:40

2017-04-04 15:00:33

2013-07-16 08:54:17

2017-01-26 23:08:19

2015-03-23 11:09:09

2017-12-19 12:06:15

2017-03-04 10:17:29