haskell学习笔记(4)-函数入门

模式匹配 (Pattern matching)

haskell可以定义同名函数,然后会根据声明顺序搜索与传入参数最接近的函数签名,然后调用那个函数,可以看成是强化版的函数重载。模式匹配的参数可以是字面量

--调用名为lucky的函数时,匹配情况为
--匹配传入参数是7的情况
lucky 7 = "LUCKY NUMBER SEVEN!" 
--匹配任意的单个传入参数
lucky x = "Sorry, you're out of luck, pal!"  

--如果声明顺序翻转,则lucky x会先于捕获所有的参数,和其他语言中(c/c++ java)搜索最接近的函数签名不同。



再看一个例子

sayMe 1 = "One!" 
sayMe 2 = "Two!" 
sayMe 3 = "Three!" 
sayMe 4 = "Four!" 
sayMe 5 = "Five!" 
sayMe x = "Not between 1 and 5"



根据此特性实现的递归阶乘

factorial 0 = 1 
factorial n = n * factorial (n - 1)



除了能够声明字面量外,函数的参数还可以是列表,元组的一部分

--捕获了一个列表的三个值,然后直接将他们相加(要实现同样的行为在java中需要在方法内取出三个值并声明局部变量)
--_表示捕获剩余的变量并抛弃
add (x:y:z:_) = x +y+z



实现一个递归的求数组长度

--递归触底返回
length' [] = 0 
--_匹配开头,xs是一个关键字,匹配所有的剩余元素,和_不同的是他可以引用,而_直接抛弃捕获到的元素,有点像正则的(?:)
--递归将length看成1+剩余部分的长度
length' (_:xs) = 1 + length' xs 



说白了,这个东西就是将一些用到的局部变量用语法糖声明在参数里了,可以少写不少代码,不过问题就是有时候比较复杂的函数声明有点难看懂。


Guards

模式匹配只能匹配精确值例如”a”,”b”,”c”,以及列表的部分例如(x:y:_),Guards则是匹配参数的域,有点像常规的switch语句。

--当其他语言的switch来看一下就理解了
bmiTell bmi
| bmi <= 18.5 = "You're underweight, you emo, you!"
| bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
| bmi <= 30.0 = "You're fat! Lose some weight, fatty!"
| otherwise = "You're a whale, congratulations!" 
bmiTell weight height
| weight / height ^ 2 <= 18.5 = "You're underweight, you emo, you!"
| weight / height ^ 2 <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
| weight / height ^ 2 <= 30.0 = "You're fat! Lose some weight, fatty!"
--otherwise就相当于其他语言switch里的default
| otherwise = "You're a whale, congratulations!" 
--声明成中缀函数的形式
a `myCompare` b 
   | a > b   = GT 
   | a == b   = EQ 
   | otherwise = LT 



haskell的Guards将一个函数分成了两部分,一部分是匹配结果值,还有一部分是where部分用于声明局部变量。想想我们往常在命令式语言里写的函数,也是先声明局部变量,然后处理,最后判断返回值。

唯一的不同就是haskell是将局部变量的声明后置,跟在where的后面

bmiTell weight height
| bmi <= 18.5 = "You're underweight, you emo, you!"
| bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
| bmi <= 30.0 = "You're fat! Lose some weight, fatty!"
| otherwise = "You're a whale, congratulations!"
--bmi就声明了一个局部变量
where bmi = weight / height ^ 2
bmiTell weight height
| bmi <= skinny = "You're underweight, you emo, you!"
| bmi <= normal = "You're supposedly normal. Pffft, I bet you're ugly!"
| bmi <= fat = "You're fat! Lose some weight, fatty!"
| otherwise = "You're a whale, congratulations!"
--声明多个局部变量
where bmi = weight / height ^ 2
skinny = 18.5
normal = 25.0
fat = 30.0

where 绑定也可以使用模式匹配,上面的where部分还可以写成

where bmi = weight / height ^ 2 
    (skinny, normal, fat) = (18.5, 25.0, 30.0)

在看一个函数的时候,应该先看where部分,再看匹配部分

where部分还可以定义函数

--在列表内部调用Bmi函数
calcBmis xs = [bmi w h | (w, h) <- xs]
--定义bmi函数,此函数只在外部函数xs内可见
   where bmi weight height = weight / height ^ 2 
calc xs=[bmi w h|(w,h)<-xs]
  where
    bmi w h=w/h^2



let 绑定与 where 绑定很相似,不同的是let是前置声明

cylinder r h =
   let sideArea = 2 * pi * r * h 
     topArea = pi * r ^2 
   in  sideArea + 2 * topArea 

欢迎关注我的github https://github.com/luckyCatMiao

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值