第一章 类型系统和函数
类型
数据类型
- Bool
- Char
- Int
- Word
- Integer
- Float Double
- String
- Tuple
- List
函数类型
类型限定 =>
:
add :: Num a => (a,a) -> a
add :: (Int, Int) -> Int
格式1
add :: (Int, Int) -> Int # 函数类型,表示给定一个整数元组返回一个整数
add (x,y) = x + y # 函数定义
函数名 :: 参数1的类型 -> 参数2的类型 -> ... -> 结果类型
函数名 参数1 参数2 ... = 函数体
add :: (Int, Int) -> Int
add (x,y) = x + y
add4 = curry add 4
::
指定函数的类型
格式2 λ表达式
函数类型 :: 参数1的类型 -> 参数2的类型 -> 结果的类型
函数名 = \参数1 -> \参数2 -> ... -> 函数体
add :: Num a => a -> a -> a
add = \x -> \y -> x + y
add4 = add 4
类型类
相等类型类 Eq
有序类型类 Ord
枚举类型类 Emum
有界类型类 Bounded
数字类型类 Num
可显示类型类 Show
表达式
条件表达式
isTwo n = if n == 2 then Ture else False
else 不能省略
情况分析表达式
month n = case n of
1 -> 31
2 -> 28
...
9 -> 30
10 -> 31
11 -> 30
12 -> 31
_ -> error "invalid month"
没有
break
关键字
守卫表达式
abs' n | n > 0 = n
| otherwise = -n
模式匹配
week mon = 1
week tus = 2
week wed = 3
week thu = 4
week fri = 5
week sta = 6
week sun = 7
列表的特殊匹配:
head' [] = error "empty"
head' (x:_) = x
第二章 模块
-
声明模块
module Test (f1, f2) where f1 = ... f2 = ... f3 = ...
-
使用模块
import Test (f1)
第三章 库函数
常用函数
-
恒值函数
> id 5 5
-
常值函数: 给定两个元素,只返回第一个
> const True 3 True
-
参数反置函数
> flip (:) [1,2,4] 5 [5,1,2,4]
-
错误函数
error "a is an error"
undefined
min / max
列表函数
null: 判定列表是否为空
length: 返回列表的长度
-
!! 取得指定第n个元素
> [1,2,3,4]!!0 1
reverse: 倒置函数
head / last
init / tail: 分别将列表的最后一个、第一个元素去掉
-
map
> map (+1) [2,3,4,5] [3,4,5,6]
filter
-
take / drop
> take 5 [1..] [1,2,3,4,5] >drop 3 [1,2,3,4,5,6] [4,5,6]
-
span / break
span: 根据一个条件,从左至右,遇到第一个不符合条件的元素时停止,将一个列表分成由两个列表组成的元组。
> span even [2,4,5,6] ([2,4],[5,6])
-
takeWhile / dropWhile
takeWhile: span 结果的第一个列表
dropWhile: span 结果的第二个列表 -
splitAt
> splitAt 5 "hello world" ("hello"," world")
-
repeat / replicate
repeat 将一个元素在列表里重复无数次
replicate 将一个元素复制 n 次
> replicate 3 3 [3,3,3]
-
any / all
> any even [1,2,3,4] True
-
elem / notElem
判断一个列表中是否存在某一元素
-
iterate
将第一个函数应用到第二个参数上多次
> iterate (*2) 1 [1,2,4,8,16,32,64...]
-
until
迭代地生成数据知道满足给定条件为止
> until (>500) (*2) 1 512
-
zip
将两个列表结合成一个元组的列表
> zip [True,False,True,False] [2,3,4,5] [(True,2),(False,3),(True,4),(False,5)]
-
concat
> concat [[1,2],[3,4]] [1,2,3,4]
-
concatMap
> map (replicate 3) [1,2,3] [[1,1,1],[2,2,2],[3,3,3]] > concatMap (replicate 3) [1,2,3] [1,1,1,2,2,2,3,3,3]
字符串函数
show: 作为字符串输出
read
lines / unlines
word / unword
递第四章 递归函数
递归在 Haskell 中很重要,命令式语言告诉你 how 计算,声明式语言让你说明 what 问题。在函数式语言中,重要的不是给出求解步骤,而是定义问题与解的描述。
# 阶乘函数
factorial :: Int -> Int
factorial n = if n < 0 then error "n is invalid"
else if n == 0 then 1
else n * factorial(n-1)
# 快排
quick' [] = []
quick' (x:xs) =
let s = [a | a <- xs, a <= x]
l = [a | a <- xs, a > x]
in quick' s ++ [x] ++ quick' l
扩展递归、尾递归
factorial n = if n == 0 then 1 else n * factorial (n-1)
mygcd x y = if y == 0 then x else mygcd y (mod x y)
- 扩展递归:递归步中除调用递归函数以外还参与了其他的函数计算,比如
mygcd
- 尾递归:进入下一个函数不再需要上一个函数的环境了,得出结果以后直接返回,比如
factorial
第五章 高阶函数
柯里函数
本质上,Haskell 所有函数只有一个参数,而之前见过的多个参数的函数都是柯里函数。柯里函数不会一次性取完所有参数,而是在每次调用时只取一个参数,并返回一个一元函数来取下一个参数。
curry / uncurry
函数组合 .
.
具有右结合性
> map ((+1).abs) [5,-2,-3,21,-12]
[6,3,4,22,13]
Point-Free 风格的代码更加简洁和易读,使你倾向思考函数的组合方式,而非数据的传递与变化。利用函数组合,可以很方便地将一组简单的函数组合在一起,使之成为一个复杂的函数。
后记
这是阅读 Haskell趣学指南 和 Haskell函数式编程入门 时所做的笔记。还会随着不断深入学习继续更新。