📅笔记

趣学指南 📅

List:

序列的基本操作

let list = [1,2,3]
head list -> [1]; head [] -> Exception
tail list -> [2,3]; tail [] -> Exception
init list -> [1,2]; init [] -> Exception
take 1 list -> [1]; take 0 list -> []; take 100 list -> list
null list -> False; null [] -> True
reverse list -> [3,2,1]; reverse [] -> []
drop 1 list -> [2,3]; drop 100 list -> []; drop 0 list -> list
minimum list -> 1; minimum [] -> Exception
maximum list -> 3; maximum [] -> Exception
sum list -> 6; sum [] -> 0;
sum “hello haskell” -> <interactive>:60:1: error:
• No instance for (Num Char) arising from a use of ‘sum’
• In the expression: sum "hello haskell"
In an equation for ‘it’: it = sum "hello haskell"
product list -> 6; product [] -> 1

使用区间

range 是构造List的方法之一,而其中的值必须是可枚举的

Ex1: 构造1到20的自然数list

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

Ex2: 1到20之间的偶数

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

Ex3: 20到1

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

如果不标明上限将会得到一个无限长度的序列,但由于Haskell是 惰性的 ,它不会对无限长度的list求值,它会等待你从list中取值
不是这种惰性......

relax.jpg

Ex4: 取前24个13的倍数
[13, 26..] -> 无限长度的序列
取出前24个 take 24 [13, 26..]

Prelude> take 24 [13,26..]
[13,26,39,52,65,78,91,104,117,130,143,156,169,182,195,208,221,234,247,260,273,286,299,312]

Ex5: cycle -> 接受一个list, 返回一个无限长度的list

Prelude> take 10 (cycle [1])
[1,1,1,1,1,1,1,1,1,1]
Prelude> take 10 (cycle [1,2])
[1,2,1,2,1,2,1,2,1,2]

Ex6: repeat -> 接收一个值,返回一个该值的无限序列

Prelude> take 10 (repeat "")
["","","","","","","","","",""]
Prelude> take 5 (repeat 5)
[5,5,5,5,5]

Ex7: replicate: replicate 3 10 => [10, 10, 10]

Prelude> replicate 3 10
[10,10,10]

List Comprehension

序列集合 => 从序列中,通过某些条件筛选出的list
Ex1: 简单示例,

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

Ex2: 添加筛选谓词

Prelude> [x*2 | x <- [1..10], x*2 >= 12, x / 3 == 0]
[]
Prelude> [x*2 | x <- [1..10], x*2 >= 12, x `mod` 3 == 0]
[12,18]

Ex3: 更加复杂的例子: 将输入的序列中小于10的奇数变为”BOOM!”, 大于10的奇数变为”BANG!”

Prelude> boombangs xs = [if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x]
Prelude> boombangs [7..17]
["BOOM!","BOOM!","BANG!","BANG!","BANG!","BANG!"]

Ex4: 编写我们自己的length函数

Prelude> length' xs = sum [1 | _ <- xs]
Prelude> length' []
0
Prelude> length' [1]
1
Prelude> length' [[1], [2]]
2

Ex5: 字符串也是list,同样适用; 过滤掉字符串中除了大写字母外的其它字符

Prelude> removeNonUppercase st = [c | c <- st, c `elem` ['A'..'Z']]
Prelude> removeNonUppercase "Hello World!"
"HW"
Prelude> removeNonUppercase "sakljMjkldsjaAdljsajlCB8312789783OOK aaaaAiiiIR"
"MACBOOKAIR"

Tuple

Tuple 简介: Tuple 和 List 很类似,都可以将多个值存入一个容器内,但是List只能存储 同种类型 的数据,而Tuple 则要求对数据的数目非常的明确。Tuple 使用()来包括内部的值。

  • Tuple 可以包含不同类型的值
  • Tuple 不可以只有一个值
  • 由于Haskell是强类型的,这样的两个tuple 无法放入 list: [(1, 2), (“g”, 10) ]将无法编译通过
  • 二元组取值 =>
Prelude> fst (1,2)
1
Prelude> fst ("haskell", 9000)
"haskell"
Prelude> snd (1,2)
2
Prelude> snd ("haskell", 1888)
1888

使用zip函数来生成List

Ex1: zip [1,2,3] [“good”, “morning”, “o”]

Prelude> zip [1,2,3]  ["good", "morning", "o"]
[(1,"good"),(2,"morning"),(3,"o")]

Ex2: 在两个list 长度不对应时在最早结束的list处断开 => zip [1,2,3] [“l”, “p”, “ui”, “op”]

Prelude> zip [1,2,3] ["l", "p", "ui", "op"]
[(1,"l"),(2,"p"),(3,"ui")]

Ex3: Haskell是惰性的,使用zip 函数同时处理有限和无限序列同样可以 =>
zip [1..] [“apple”, “orange”, “mango”, “pear”]

Prelude> zip [1..] ["apple", "orange", "mango", "pear"]
[(1,"apple"),(2,"orange"),(3,"mango"),(4,"pear")]

Ex4: 使用元组解决实际问题 =>
取得所有三边长度皆为整数且小于等于10,周长为24的直角三角形

Prelude> let trangles' = [(a,b,c) | c <- [1..10], a <- [1..c], b <- [1..a], a^2 + b^2 == c^2, a + b + c == 24]
Prelude> print trangles'
[(8,6,10)]

Types and Type-classes

Haskell 是 静态类型 语言

=> 在编译时每个表达式的类型已经完全确定。
=> 如果程序中有布尔值与整数相除的动作,将不会通过编译。

Haskell 有类型推导

=> let a = 3, 不用告诉编译器a 是Int类型

使用 :t 在ghci中查询数据类型

Prelude> :t 'a'
'a' :: Char
Prelude> :t "hello"
"hello" :: [Char]

同样,函数也有类型,并且对于函数来说,标明类型将使代码更加清晰

=> 三个数相加:
addThree :: Int -> Int -> Int -> Int ; addThree a b c = a + b + c

Prelude> addTwo :: Int -> Int -> Int; addTwo a b =  a + b
Prelude> addTwo 99 1
100

常见数据类型

=> Int : 整数,有上限和下限
=> Integer: 整数,无上下限,只和当前机器存储有关
=> Float: 单精度浮点
=> Double: 双精度浮点
=> Bool
=> Char
=> Tuple


Type Variables 泛型

head 函数的类型

=>

Prelude> :t head
head :: [a] -> a

类型名都是大写的,a并没有大写,所以a不会是一个类型。a是一个类型变数,意味着a可以是任意类别,和泛型非常类似。

使用类别变数构造的函数称为’多态函数’,这样我们可以编写出更多与类型无关的函数

=>

Prelude> :t fst
fst :: (a, b) -> a

Typeclasses

如果某一个类型属于某一种Typeclass,则这个类型必然实现了该Typeclass所描述的行为。和OC中的协议非常类似

=> ‘==‘函数的类型

Prelude> :t (==)
(==) :: Eq a => a -> a -> Bool

Eq即为a的Typeclass, 调用该函数的类型一定是遵守了Eq所描述的行为的

常用的Typeclasses

=> Eq: 可判断相等性的类型。除函数外的所有类型都实现了Eq,都可以比较大小
=> Ord: 包含可比较大小的类型。Ord包中包含了 > < >= <= 之类的用于比较大小的函数。compare函数比较两种相同类型的值,返回结果为GT(greater than) LT(less than) EQ(equal)

Prelude> 5 `compare` 3
GT 
Prelude> "A" `compare` "Z"
LT

=> Show: 包含可用字符串表示的类型。

Prelude> show True
"True"
Prelude> show [1,2,3]
"[1,2,3]"

// 函数无法show
Prelude> add8 :: Int -> Int; add8 a = a + 8 
Prelude> show add8
<interactive>:159:1: error:
    • No instance for (Show (Int -> Int)) arising from a use of ‘show’
        (maybe you haven't applied a function to enough arguments?)
    • In the expression: show add8
      In an equation for ‘it’: it = show add8

=> Read: 和Show相反,表示可以从字符串转换成某种类型的Typeclass。

Prelude> read "[1,2,3,4]" ++ [5]
[1,2,3,4,5]

// 无法直接推断出想要转换的类型
Prelude> read "4"
*** Exception: Prelude.read: no parse

// 可以直接指定转换的类型
Prelude> read "4" :: Int
4

=> Enum: 可枚举类型,“該 Typeclass 包含的型別有:(), Bool, Char, Ordering, Int, Integer, Float 和 Double”

=> Bounded: 有上下限的数据,使用maxBound和minBound输出上下限

Prelude> maxBound :: Bool
True
Prelude> minBound :: Int
-9223372036854775808

=> Num: 表示数字的Typleclass,它的成员都有数字的特征。

Prelude> :t (*)
(*) :: Num a => a -> a -> a

=> Integer: 仅仅代表整数的Typeclass,成员有Int 和Integer


补充

Q1: 类型是干什么用的?
Ans: 在计算机的最底层,处理的都是没有任何附加结构的字节(Byte)。类型系统在这个基础上进行了抽象:为那些单纯的字节加上了意义,使得我们可以说“这些字节是文本”, “那些字节是机票预约数据”等等。

Q2: Haskell 类型系统的特点
Ans:

  1. 强类型的
  2. 静态的
  3. 自动类型推导
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容