- 1、本文档共5页,可阅读全部内容。
- 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
第四章 函数的语法
模式匹配
注意,门卫!
Where?
Let it be
case表达式
模式匹配
本章讲的就是haskell那套酷酷的语法结构,先从模式匹配开始。模式匹配通过 查数
据的特定结构来 查其是否匹配,并按模式从中取得数据。
在定义函数时,你可以为不同的模式分别定义函数体,这就让代码更加简洁易读。你
可以匹配⼀切数据类型数字,字符,List ,元组,等等。我们弄个简单函数,让它
查我们传给它的数字是不是7 。
lucky :: (Integral a) = a - String
lucky 7 = LUCKY NUMB R S V N!
lucky x = Sorry, youre out of luck, pal!
在调⽤lucky时,模式会从上⾄下进⾏ 查,⼀旦有匹配,那对应的函数体就被应⽤
了。这个模式中的唯⼀匹配是参数为7 ,如果不是7 ,就转到下⼀个模式,它匹配⼀切
数值并将其绑定为x 。这个函数完全可以使⽤if实现,不过我们若要个分辨1到5 中的数
字,⽽⽆视其它数的函数该怎么办?要是没有模式匹配的话,那可得好⼤⼀棵if-else
树了 !
sayMe :: (Integral a) = a - String
sayMe 1 = One!
sayMe 2 = Two!
sayMe 3 = Three!
sayMe 4 = Four!
sayMe 5 = Five!
sayMe x = Not between 1 and 5
注意下,如果我们把最后匹配⼀切的那个模式挪到最前,它的结果就全都是Not
between 1 and 5 了。因为它⾃⼰匹配了⼀切数字,不给后⾯的模式留机会。
记得前⾯实现的那个阶乘函数么?当时是把n的阶乘定义成了product [1..n]。也
可以写出像数学那样的递归实现,先说明0 的阶乘是1,再说明每个正整数的阶乘都是
这个数与它前驱(predecessor)对应的阶乘的积。如下便是翻译到haskell的样⼦:
factorial :: (Integral a) = a - a
factorial 0 = 1
factorial n = n * factorial (n - 1)
这就是我们定义的第⼀个递归函数。递归在haskell 中⼗分重要,我们会在后⾯深⼊理
解。如果拿⼀个数 (如3 )调⽤factorial函数,这就是接下来的计算步骤:先计算
3*factorial 2,factorial 2等于2*factorial 1,也就是3*(2*
(factorial 1))。factorial 1等于1*factorial 0,好,得3*(2*
(1*factorial 0)),递归在这⾥到头了,嗯我们在万能匹配前⾯有定义,0 的阶
乘是1.于是最终的结果等于3*(2*(1*1))。若是把第⼆个模式放在前⾯,它就会捕获
包括0在内的⼀切数字,这⼀来我们的计算就永远都不会停⽌了。这便是为什么说模
式的顺序是如此重要:它总是优先匹配最符合的那个,最后才是那个万能的。
模式匹配也会失败。假如这个函数:
charName :: Char - String
charName a = Albert
charName b = Broseph
charName c = Cecil
拿个它没有考虑到的字符去调⽤它,你就会看到这个:
ghci charName a
Albert
ghci charName b
Broseph
ghci charName h
*** xception: tut.hs:(53,0)-(55,21): Non-exhaustive patterns in
它告诉我们说,这个模式不够全⾯。因此,在定义模式时,⼀定要留⼀个万能匹配的
模式,这样我们的程序就不会为了不可预料的输⼊⽽崩溃了。
对T ple 同样可以使⽤模式匹配。写个函数,将⼆维空间中的向量相加该如何?将它们
的x项和y项分别相加就是了。如果不了解模式匹配,我们很可能会写出这样的代码:
addVectors :: (Num a) = (a, a) - (a, a) - (a, a)
addVectors a b = (fst a + fst b, snd a + snd b)
嗯,可以运⾏。但有更好的
文档评论(0)