当前位置: 代码迷 >> 综合 >> Haskell 笔记 (二)基本知识
  详细解决方案

Haskell 笔记 (二)基本知识

热度:32   发布时间:2023-12-13 06:13:57.0

基本知识

逻辑运算符

逻辑 运算符
布尔值 Ture, False
逻辑与 &&
逻辑或
逻辑非 not
相等,不相等 ==, /=

函数

前缀函数(prefix function):大多数为前缀函数,调用时格式为:先是函数名,后跟参数列表,中间都是空格分开, 如: min 8 2
中缀函数(infix function): *就是中缀函数,夹在两个参数中间。

通过’'可以将前缀函数,转换为中缀函数:

//前缀形式
ghci> div 80 16

等价为:

//中缀形式
ghci> 80 'div' 16

列表

列表运算符
运算符 功能 例子
++ 拼接两个列表 [1, 3, 5] ++ [6]=>[1, 3, 5, 6]
: 将元素插入表头 [1] : [2, 3, 5, 6] => [1, 2, 3, 5, 6]
!! 访问列表中元素, 下标从0开始 [1, 3, 5] !! 1 => 3
<,>,<=,>= 比较两个列表大小 [3, 2, 1] > [2, 1, 0]=>True
列表函数
函数 功能 例子
head 返回列表的头部,也就是第一个元素 head [5, 4, 3, 2, 1]=>5
tail 返回列表的尾部,也就是除了头部之后的部分 tail [5, 4, 3, 2, 1]=>[4, 3, 2, 1]
last 返回列表的最后一个元素 last [5, 4, 3, 2, 1]=>1
init 返回列表除了最后一个元素的部分 init [5, 4, 3, 2, 1]=>[5, 4, 3, 2]
length 返回列表的长度 length [5, 4, 3, 2, 1]=>5
null 检查列表是否为空 null [5, 4, 3, 2, 1]=>False
reverse 反转列表 reverse [5, 4, 3, 2, 1]=>[1, 2, 3, 4, 5]
take 返回指定列表的前几个元素 take 2 [5, 4, 3, 2, 1]=>[5, 4]
drop 删除指定列表的前几个元素 drop 2 [5, 4, 3, 2, 1]=>[3, 2, 1]
maxinum 返回列表的最大的元素 maxinum [5, 4, 3, 2, 1]=>5
mininum 返回列表的最小的元素 mininum [5, 4, 3, 2, 1]=>1
sum 返回列表的所有元素的和 sum [5, 4, 3, 2, 1]=>15
product 返回列表的所有元素的积 product [5, 4, 3, 2, 1]=>120
elem 判断一个元素是否在列表中 elem 4 [5, 4, 3, 2, 1]=>True

区间

通过区间可以构造列表,其中的值必须是可枚举的,或者说,是可以排序的。

Prelude> [1..20]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
Prelude> ['a'..'z']
"abcdefghijklmnopqrstuvwxyz"
Prelude> ['K'..'Z']
"KLMNOPQRSTUVWXYZ"
Prelude>

区间可以调整步长

Prelude> [2, 4..20]
[2,4,6,8,10,12,14,16,18,20]
Prelude> [3, 6..20]
[3,6,9,12,15,18]

为什么[2, 2…20]不行?

Prelude> [2,2..20]
[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,22,2,2,2,2,2...

步长不是第一个数,而是通过第二个数减去第一个数计算出来的。
[2,2…20]:2-2=0, 步长成了0,一直不会到20,所以结束不了。

[20…1] 为什么为空?

ghci>[20..1]
[]

[20…1]没有提供步长,Haskell会默认构造一个空的列表,随后从区间的下限开始,不停的增长等于上限为止,20已经大于1了,所以是空。

也就是说步长默认是+1的,如果是-1,必须提供步长,[20,19…1]

ghci>[20,19..1]
[20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1]

如果不表明区间上限,将得到一个无限长度列表

ghci>[20,19..]
[20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18,-19,-20,-21,-22,-23,-24,-25,-26,-27,-28,-29,-30,-31,-32,-33,-34,-35,-36,-37,-38,-39,-40,-41,-42,-43,-44,-45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-57,-58,-59,-60,-61,-62,-63,-64,-65,-66,-67,-68,-69,-70,-71,-72,-73,-74,-75,-76,-77,-78,-79,-80,-81,-82,-83,-84,-85,-86......

可以通过take取前几个

ghci>take 10 [20,19..]
[20,19,18,17,16,15,14,13,12,11]

另外几种生成无限列表的函数:

  1. cycle 函数: 接受一个列表作为参数,并返回一个无限列表
ghci>take 10 (cycle [1, 2, 3])
[1,2,3,1,2,3,1,2,3,1]
ghci>take 14 (cycle "LOL ")
"LOL LOL LOL LO"
  1. repeate 函数: 接受一个值作为参数,并返回一个无限列表
ghci>take 10 (repeat 6)
[6,6,6,6,6,6,6,6,6,6]
  1. replicate 函数: 一个参数表示列表的长度,一个参数表示要复制的值。
ghci>replicate 10 6
[6,6,6,6,6,6,6,6,6,6]

由于浮点数只能实现有限精度,最好不要在区间中使用浮点数。

ghci>[0.1, 0.2..1]
[0.1,0.2,0.30000000000000004,0.4,0.5,0.6,0.7000000000000001,0.8,0.9,1.0]
ghci>[0.1, 0.3..1]
[0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]

列表推导式

列表推导式是一种过滤,转换或者组合列表的方法

ghci> [x*2 | x <- [1..10]]
[2,4,6,8,10,12,14,16,18,20]

“|” 后 x <- [1…10] : x绑定1-10每个元素

“|” 前 x*2 : 输出

还可以对绑定值增加过滤,形式为[输出 | 绑定,过滤],

如[x*2 | x <- [1…10], x > 12]

ghci> [x*2 | x <- [1..10], x*2 > 12]
[14,16,18,20]
ghci> [x*2 | x <- [1..10], x > 6]
[14,16,18,20]

将推导式设置为函数, xs是列表,绑定到x,对其中x为奇数的执行“ if x < 10 then “BOOM!” else “BANG!” ”

x <- xs, odd x 使x绑定到 7, 9, 11, 13

ghci> boomBangs xs = [ if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x]
ghci> boomBangs [7..13]
["BOOM!","BOOM!","BANG!","BANG!"]

多个列表,结果是多个表元素的组合情况

ghci> [x + y | x <- [1..5], y <- [10, 100, 1000]]
[11,101,1001,12,102,1002,13,103,1003,14,104,1004,15,105,1005]
ghci> [x * y | x <- [1..5], y <- [10, 100, 1000]]
[10,100,1000,20,200,2000,30,300,3000,40,400,4000,50,500,5000]

元组

元组: 将多个异构的值合成为一个单一值。长度固定。

长度为2的元组叫做序对(pair)
长度为3的元组叫做三元组(triple)

序对的操作:

  1. fst : 返回首项
  2. snd : 返回尾项
  3. zip : 通过2个列表生成序对, 2个列表不一样长时,以短的为准。

例题:
使用Haskell找出满足下列条件的三角形

  • 三个表都为整数
  • 三个边长度都小于等于10
  • 周长为24的三角形
ghci> [(x,y,z) | x<-[1..10], y<-[1..10], z<-[1..10], x*x + y*y ==z*z, x+y+z==24]
[(6,8,10),(8,6,10)]

解题思路:先初始化集合将其变形,在通过过滤条件缩小计算范围。