博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Haskell趣学指南》笔记之函数
阅读量:6072 次
发布时间:2019-06-20

本文共 2658 字,大约阅读时间需要 8 分钟。

系列文章


模式匹配

写好模式,Haskell 会直接帮你匹配。如:

lucky :: Int -> Stringlucky 7 = "7 is the lucky number!"lucky x = "sorry, you are not lucky"复制代码

载入之后运行

λ> lucky 2"sorry, you are not lucky"λ> lucky 3"sorry, you are not lucky"λ> lucky 7"7 is the lucky number!"复制代码

但是注意,如果把 lucky x 挪到 lucky 7 前面,就永远匹配不到 lucky 7 了。

  • 用模式匹配实现阶乘:
factorial :: Int -> Int factorial 0 = 1 factorial n = n * factorial (n - 1)复制代码
  • 定义模式的时候,一定在最后留一个万能模式,否则可能会出错
  • 元组的模式匹配
addVectors :: (Double, Double) -> (Double, Double) -> (Double, Double) addVectors a b = (fst a + fst b, snd a + snd b)-- 可以改写为addVectors :: (Double, Double) -> (Double, Double) -> (Double, Double) addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)复制代码
  • 模式中可以用 _ 来占位,这个 _ 叫做泛变量
  • 可以用 x: _ 来匹配列表的第一个元素 x,但是要记得加圆括号,不然 Haskell 无法理解它
head' :: [a] -> a head' [] = error "Can' t call head on an empty list, dummy!" -- error 会中断程序head' (x:_) = x -- 这里的圆括号不是 tuple 的标记复制代码
  • 匹配只有一个元素的列表,可以用 [x],也可以用 (x:[])
  • 匹配只有两个元素的列表,可以用 [x,y],也可以用 (x:y:[])
  • 匹配大于两个元素的列表,用 (x:y:_),不能用 [] 的形式
  • as 模式:all@(x:items) 中的 all 表示整个 x:items 列表,方便后面引用

守卫/哨卫 guard

bmiTell :: Double -> String bmiTell weight height        | weight / height ^ 2 <= 18.5 = putStrLn "你体重不足,就像根竹竿!"    | weight / height ^ 2 <= 25.0 = putStrLn "你体重正常,那你肯定是个丑逼!"        | weight / height ^ 2 <= 30.0 = putStrLn "你体重超过,快减肥吧肥宅!"        | otherwise                        = putStrLn "你是猪!"复制代码

其中的 bmi < 18.5 就是一个 guard。 每条 guard 语句至少缩进一个空格。 如果当前模式的守卫都没有 True,而且也没有写 otherwise,就会进入下一个模式。

where

可以使用 where 来对计算结果进行缓存,也可以定义其他的帮助函数:

bmiTell :: Double -> String bmiTell weight height        | bmi <= 18.5 = putStrLn "你体重不足,就像根竹竿!"    | bmi <= 25.0 = putStrLn "你体重正常,那你肯定是个丑逼!"        | bmi <= 30.0 = putStrLn "你体重超过,快减肥吧肥宅!"        | otherwise     = putStrLn "你是猪!"    where bmi = weight / height ^ 2             x = "whatever"             getBmi weight height = weight / height ^ 2复制代码

where 只在当前模式中有效。

就算没有 guard,也可以在函数定义中使用 where:

calcBmis :: [(Double, Double)] -> [Double] calcBmis xs = [bmi w h | (w, h)< - xs]         where bmi weight height = weight / height ^ 2复制代码

what 还能这样用

describeList :: [a] -> StringdescribeList ls = "The list is " ++ what ls    where what [] = "empty."             what [x] = "a singleton list."             what xs = "a longer list."复制代码

其中 what ls 是以 ls 为参数调用 what 函数。

let

ghci> 4 * (let a = 9 in a + 1) + 2 42复制代码

let 和 where 相似,不同点在于 where 只允许我们在函数底部绑定变量,且对当前模式可见。而 let 可以出现在任何地方,且 let 里面的变量只在 in 内有效。

另一个区别就是 let 是表达式(有值),而 where 不是。

case

case 
of pattern1 -> result1 pattern2 -> result2 pattern3 -> result3复制代码

模式匹配不过是 case 的语法糖,而且模式匹配只能用在函数定义里,而 case 可以用在任何地方。

转载于:https://juejin.im/post/5ccd9ec9f265da03705fc78a

你可能感兴趣的文章
灵活的运用Model类
查看>>
hadoop 之分布式安装
查看>>
使用ansible工具部署ceph
查看>>
linux系列博文---->深入理解linux启动运行原理(一)
查看>>
Android反编译(一) 之反编译JAVA源码
查看>>
结合当前公司发展情况,技术团队情况,设计一个适合的技术团队绩效考核机制...
查看>>
python-45: opener 的使用
查看>>
cad图纸转换完成的pdf格式模糊应该如何操作?
查看>>
Struts2与Struts1区别
查看>>
网站内容禁止复制解决办法
查看>>
Qt多线程
查看>>
我的友情链接
查看>>
Ubuntu12.04 编译android源代码及生成模拟器经历分享
查看>>
KVM网络桥接设置方法
查看>>
Puppet学习手册:Puppet Yum安装
查看>>
我的友情链接
查看>>
ansible学习记录
查看>>
网思科技校园网计费解决方案
查看>>
我的友情链接
查看>>
携程 Apollo分布式部署
查看>>