文档详情

第四章 函数的语法.pdf

发布:2017-05-27约5.28千字共5页下载文档
文本预览下载声明
第四章 函数的语法 模式匹配 注意,门卫! 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) 嗯,可以运⾏。但有更好的
显示全部
相似文档