系列文章
- 《Haskell趣学指南》笔记之基本语法
- 《Haskell趣学指南》笔记之类型(type)
- 《Haskell趣学指南》笔记之函数
- 《Haskell趣学指南》笔记之高阶函数
- 《Haskell趣学指南》笔记之模块
- 《Haskell趣学指南》笔记之自定义类型
- 《Haskell趣学指南》笔记之I/O
前言
- Haskell 是纯函数式的(不能赋值,引用透明)
- Haskell 是 lazy 的
- Haskell 是静态类型的
- Haskell 支持类型推导
:l myfunctions可以加载同目录的 myfunctions.hs,且可以重复执行:set prompt "ghci> "可以改 prompt:set prompt "λ "可以得到 λ- 把这句话写在 ~/.ghci 里试试
- putStrLn 可以打印出中文字符串
第 1 章
5 * -3要写成5 * (-3),不然报错- 布尔用 True 和 False
1 + '1'会报错,5 + 0.4不报错,因为 5 也可以被看作 5.0
函数
- Haskell 中有一些中缀函数,如 * 和 +
- 只要以特殊字符命名函数,即可自动将它视为中缀函数。
- Haskell 大部分属于前缀函数,如
succ 8是取后继min 1 2是取最小max 1 2是取最大div 9 3是除法
- 函数调用的优先级最高,
succ 9 * 10等价与(succ 9) * 10 - 前缀可以变中缀:
div 9 3可以改成9 `div` 3 - 单参数函数
doubleMe x = x + x - 双参数函数
doubleUs x y = x * 2 + y * 2 - 函数定义没有先后顺序的概念
- 条件语句
if <condition> then <exp> else <exp>不能省略 else - 条件语句是表达式而不是语句,总是有返回值
- 函数名可以包含
'字符,一般以'结尾的函数是非惰性求值版本,也叫严格求值 - 函数名不能以大写字母开头,因为大写字母开头的是类型
- 没有参数的函数被称为定义或者名字,如
a = 1
列表
- 列表是单类型 homogeneous 的数据结构,只能存储类型相同的元素,不能储存类型不同的元素
a = [1,2,3]- 使用
++可以拼接两个列表,但是它会遍历第一个列表 "hello"是['h','e','l','l','o']的语法糖- 使用 Cons 运算符
:可以在列表头部插入一个元素1:[2,3] [1,2]是1:2:[]的语法糖- 按索引获取值可以用
!!符号:[1,2,3] !! 0值为 1,索引越界会报错 [3, 2, 1] > [2, 1, 0]值为 True- 更多列表操作:
head/tail/last/init/length/null/reverse/task 3/drop 3/maximum/minimum/sum/product求积
head []报错4 `elem` [3,4,5]值为 True[1..20]生成 1 到 20 这 20 个数字组成的列表['a'..'z']/['K'..'Z'][2,4..20]生成 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20][20..1]会得到空列表,应该写成[20,19..1]take 24 [13, 26..]cycle [1, 2, 3]会对列表进行无限循环,得到 1,2,3,1,2,3,1,2,3... 组成的列表repeat 5会得到由 5 组成的无限列表repeat 3 10会得到 [10,10,10]
列表推导式
[x* 2 | x <- [1.. 10]]得到 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20][x* 2 | x <- [1.. 10], x>5, filter2, filter3]可以对 x 进行过滤[ x* y | x <-[1, 3, 5], y <- [2, 4, 6]]得到长度为 9 的列表 [2,4,6,6,12,18,10,20,30][ x* y | x <-[1, 3, 5], y <- [2, 4, 6], x* y > 10]得到 [12,18,20,30]length' xs = sum [1 | _ <- xs]可以使用这个 length' 函数求列表的长度- 还能嵌套:
ghci> xxs = [[1, 3, 5, 2, 3, 1, 2, 4, 5],[ 1, 2, 3, 4, 5, 6, 7, 8, 9],[ 1, 2, 4, 2, 1, 6, 3, 1, 3, 2, 3, 6]] ghci> [ [ x | x <- xs, even x ] | xs <- xxs] [[2, 2, 4],[ 2, 4, 6, 8],[ 2, 4, 2, 6, 2, 6]]
元组 tuple
- tuple 可以容纳不同类型的值,也就是说它是异构的
- tuple 的长度是固定的,不能改变
(1,3)是 tuple,(1,'a', "hello")也是 tuple- 长度为 2 的元组也叫序对 pair
- 二元组和三元组的类型被视为不同,所以
[(1,2), (3,4,5)]会报错,因为列表只能包含相同类型的东西 - 长度相同,但是里面元素的类型如果不同,两个 tuple 的类型也会被视为不同
- 不允许长度为 1 的元组,因为这没有意思
- 序对相关 API
- fst (8,11) => 8
- snd (8,11) => 11
- zip [1,2,3] [4,5,6] => [(1,4),(2,5),(3,6)]
- 如果 zip 的两个参数的长度不同,那么就会舍弃多余的项