• 本 Handout 备份于此处。（不保证与源文件同步）
• Read also Chapter 4 of the text book "Programming in Haskell.

## 概述​

1. Composition of existing functions
2. Conditionals (if _ then _ else _ )
3. Guarded equations
4. Pattern matching
5. Lambda expressions

## 组成函数 Composing functions​

A video for this section, including explanation of the exercise, is here.

removeLast :: [a] -> [a]
removeLast xs = reverse (tail (reverse xs))

removeElem :: Int -> [a] -> [a]
removeElem n xs = removeLast (take n xs) ++ drop n xs

removeFirstAndLast :: [a] -> [a]
removeFirstAndLast xs = removeLast (removeElem 1 xs)

## 条件式 Conditionals​

Haskell provides if _ then _ else _. It is typed Bool -> a -> a -> a, 多态地.

abs' :: Integer -> Integer
abs' n = if n >= 0 then n else -n

Note: The else branch is 强制性.

We can nest if _ then _ else _:

howMuchDoYouLikeHaskell x = if x < 3 then "I dislike it!" else
if x < 7 then "It's ok!" else
"It's fun!"

## 受保护的方程式 Guarded equations​

A video for this section, including explanation for the exercise, is here.

Guarded equations are an alternative to if _ then _ else _ expressions. They are often more readable:

abs :: Int -> Int
abs n | n >= 0 = n
| otherwise = -n

Here, n >= 0 and otherwise are called guards; 它们是布尔运算。 The function returns the value after the first guard that evaluates to True.

Guarded equations are more convenient to use than if _ then _ else _:

howMuchDoYouLikeHaskell2 x | x < 3 = "I dislike it!"
| x < 7 = "It's ok!"
| otherwise = "It's fun!"

answer :: Int -> Int -> Bool
answer x y | x > y && x < 2 * y = True
| otherwise = False

## 模式匹配 Pattern matching​

### 概述​

notB :: Bool -> Bool
notB False = True
notB True = False

swap :: (a, b) -> (b, a)
swap (x,y) = (y,x)

isEmpty :: [a] -> Bool
isEmpty [] = True
isEmpty (x:xs) = False

### 关于布尔运算 On Booleans​

notB' :: Bool -> Bool
notB' False = True
notB' True = False

andB :: Bool -> Bool -> Bool
andB True True = True
andB True False = False
andB False True = False
andB False False = False

andB' :: Bool -> Bool -> Bool
andB' True True = True
andB' _ _ = False

andB'' :: Bool -> Bool -> Bool
andB'' True b = b
andB'' False _ = False

orB :: Bool -> Bool -> Bool
orB True _ _ = True
orB _ True _ = True
orB _ _ True = True

### 非穷举模式 Non-exhaustive patterns​

isTrue :: Bool -> Bool
isTrue True = True

*Main> isTrue False
*** Exception: defining-functions.hs:36:1-18: Non-exhaustive patterns in function isTrue

isTrue' :: Bool -> Bool
isTrue' True = True
isTrue' False = error "not True"

### 关于图元 On tuples​

fst :: (a,b) -> a
fst (x,y) = x

snd :: (a,b) -> b
snd (_,y) = y

third :: (a, b, c) -> c
third (_, _, z) = z

addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a)
addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)

swap :: (a, b) -> (b, a)
swap (1, 2) = (2, 1)

### 关于名单 On lists​

1. 空列表；或
2. of the form x:xs for x :: a and xs :: [a].
isEmpty' :: [a] -> Bool
isEmpty' [] = True
isEmpty' (x:xs) = False

isEmpty'' :: [a] -> Bool
isEmpty'' [] = True
isEmpty'' (_:_) = False

sndElem :: [a] -> a
sndElem (_:x:_) = x

### 案例表达 Case expressions​

isEmpty2 :: [a] -> Bool
isEmpty2 x = case x of [] -> True
(_:_) -> False

## Lambda 表达式 Lambda expressions​

Lambda 表达式是无名的函数。它们在高阶函数中特别有用，这将在后面的课程中讨论。

A video accompanying this section is here.

double :: Int -> Int
double x = 2 * x

double' :: Int -> Int
double' = \x -> 2 * x

Lambda 表达式可以有多个输入变量。

mult :: Int -> Int -> Int
mult x y = x * y

mult' :: Int -> Int -> Int
mult' = \x y -> x * y

mult'' :: Int -> (Int -> Int)
mult'' = \x -> (\y -> x * y)

alwaysZero :: Bool -> Int
alwaysZero = \_ -> 0

lambda 表达式的一个重要应用是高阶函数，其中函数是其他函数的参数。请考虑：

apply :: (a -> b) -> a -> b
apply f x = f x
*Main> apply (\_ -> 5) 'r'
5
*Main> apply (\ x -> if x < 0 then "Less than zero!" else "Greater or equal than zero!") (-3)
"Less than zero!"

## Operators and sections​

There is also a video on operators and sections.

1. 任何二进制函数都可以通过用反斜线括起来变成一个运算符。例如：div 7 2 可以写成 7 div 2
2. 反过来说，任何运算符都可以用小括号括起来作为前缀，例如，(:) 1 [2,3]

1. (⊗) :: a -> b -> c. Here, (⊗) = \x y -> x ⊗ y.
2. (x ⊗) :: b -> c, where x :: a. Here, (x ⊗) = \y -> x ⊗ y.
3. (⊗ y) :: a -> c, where y :: b. Here, (⊗ y) = \x -> x ⊗ y.

Sections 可以用来简明地定义函数。

square :: Int -> Int
square = (^2)

reci :: Fractional a => a -> a
reci = (1 /)

2. 在使用高阶函数编程时，Sections 是非常有用的（参见后面的课程）。

## 练习​

1. 定义一个函数 third :: [a] -> a 的三个变体，该函数返回任何包含至少这么多元素的列表中的第三个元素，使用
2. list indexing !!
3. pattern matching
2. 定义一个函数 safetail :: [a] -> [a]，除了将 [] 映射到 []（而不是抛出一个错误），它的行为与 tail 相似。使用 tailisEmpty :: [a] -> Bool。 定义 safetail，使用
1. a conditional expression
2. guarded equations
3. pattern matching