# Haskell 学习笔记 (1)

最近在学 *Haskell* ，东西比较零碎，所以把代码片段记下来吧。看的是《Haskell 趣学指南》 (*Learn You a Haskell for Great Good*)

- 函数结合优先级最高
- 一些常用的函数及其用法
`min`

和`max`

只接受两个参数`maximum`

和`minimum`

接受列表`++`

用于拼接列表，复杂度为左侧字符串长度`:`

用于将一个元素从左侧拼入列表- 列表可以根据字典序比较
`take`

数量超过整个列表则会返回整个列表`drop`

数量超过整个列表则会返回空列表`[1..]`

支持无限列表`[5,4..]`

支持指定步长

```
succ 9 + max 5 4 + 1 -- 16
pred 8 -- 7
succ 8 -- 9
min 9 10 -- 9
max 9.1 9.9 -- 9.9
[1,2,3,4] ++ [9,10,11,12] -- [1,2,3,4,9,10,11,12]
'A':" small cat" -- "A small cat"
[1,2,3,4] > [1,2,3] -- True
head [1,2,3,4,5] -- 1
tail [1,2,3,4,5] -- [2,3,4,5]
last [1,2,3,4,5] -- 5
init [1,2,3,4,5] -- [1,2,3,4]
length [1,2,3,4,5] -- 5
null [] -- True
reverse [1,2,3,4,5] -- [5,4,3,2,1]
take 3 [1,2,3,4,5] -- [1,2,3]
take 10 [1,2,3,4,5] -- [1,2,3,4,5]
drop 3 [1,2,3,4,5] -- [4,5]
drop 10 [1,2,3,4,5] -- []
maximum [1,2,3,4,5] -- 5
minimum [1,2,3,4,5] -- 1
sum [1,2,3,4,5] -- 15
product [1,2,3,4,5] -- 120
4 `elem` [1,2,3,4,5] -- True
[1..5] -- [1,2,3,4,5]
[5,4..1] -- [5,4,3,2,1]
take 5 [3,6..] -- [3,6,9,12,15]
take 10 (cycle [1,2,3]) -- [1,2,3,1,2,3,1,2,3,1]
take 10 (repeat 5) -- [5,5,5,5,5,5,5,5,5,5]
replicate 10 5 -- [5,5,5,5,5,5,5,5,5,5]
[0.1, 0.3 .. 1] -- [0.1,0.3,0.5,0.7,0.899999,1.099999]
[ x*2 | x <- [1..10]] -- [2,4,6,8,10,12,14,16,18,20]
[ x | x <- [1..10], x /= 3, x /= 7, x /= 9] -- [1,2,4,5,6,8,10]
[ x+y | x <- [1,2,3], y <- [10,20,30]] -- [11,21,31,12,22,32,13,23,33]
[(1,0,0), (0,1,0), (0,0,1)]
fst (1,2) -- 1
snd (1,2) -- 2
zip [1..] ["one", "two", "three", "four", "five"]
-- [(1,"one"),(2,"two"),(3,"three"),(4,"four"),(5,"five")]
```

- 一些函数
- 类型
- 模式匹配
- 递归函数设计
- 用
`guard`

防止大坨`if-else`

`where`

和`let ... in ...`

`case`

模式匹配

```
length' xs = sum [1 | _ <- xs]
:t [(1,0,0), (0,1,0), (0,0,1)]
:t zip
5 `compare` 3
show [(1,0,0), (0,1,0), (0,0,1)]
read "[1,2,3,4]" ++ [5]
read "[1,2,3,4]" :: [Int]
sayMe :: Int -> String
sayMe 1 = "One!"
sayMe 2 = "Two!"
sayMe 3 = "Three!"
sayMe x = "Not between 1 and 3"
factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial (n-1)
addVectors :: (Double, Double) -> (Double, Double) -> (Double, Double)
addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
head' :: [a] -> a
head' [] = error "Can't call head' on an empty list."
head' (x:_) = x
firstletter :: String -> String
firstletter "" = "Empty String."
firstletter all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]
bmiTell :: Double -> String
bmiTell weight height
| bmi <= skinny = "You're underweight."
| bmi <= normal = "You're supposedly normal."
| bmi <= fat = "You're fat."
| otherwise = "You're a whale."
where bmi = weight / height^2
skinny = 18.5
normal = 25.0
fat = 30.0
calcBmis :: [(Double, Double)] -> [Double]
calcBmis xs = [bmi w h | (w, h) <- xs]
where bmi weight height = weight / height^2
(let (a, b, c) = (1, 2, 3) in a+b+c) * 100
calcBmis' :: [(Double, Double)] -> [Double]
calcBmis' xs = [bmi | (w, h) <- xs, let bmi = w / h^2, bmi > 25.0]
describeList :: [a] -> String
describeList ls = "The list is " ++ case ls of [] -> "empty."
[x] -> "a singleton list."
xs -> "a longer list."
take' :: (Num i, Ord i) => i -> [a] -> [a]
take' n _
| n <= 0 = []
take' _ [] = []
take' n (x:xs) = x : take' (n-1) xs
reverse' :: [a] -> [a]
reverse' [] = []
reverse' (x:xs) = reverse' xs ++ [x]
repeat' :: a -> [a]
repeat' x = x : repeat' x
zip' :: [a] -> [b] -> [(a, b)]
zip' _ [] = []
zip' [] _ = []
zip' (x:xs) (y:ys) = (x,y):zip' xs ys
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let smallerOrEqual = [a | a <- xs, a <= x]
larger = [a | a <- xs, a > x]
in quicksort smallerOrEqual ++ [x] ++ quicksort larger
```