《Haskell趣学指南》笔记之函数

栏目: 编程语言 · 发布时间: 5年前

内容简介:写好模式,Haskell 会直接帮你匹配。如:载入之后运行但是注意,如果把 lucky x 挪到 lucky 7 前面,就永远匹配不到 lucky 7 了。

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

lucky :: Int -> String
lucky 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:y:_)
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] -> String
describeList 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 <exp> of pattern1 -> result1
                    pattern2 -> result2
                    pattern3 -> result3
复制代码

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


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

用数据讲故事

用数据讲故事

[美] Cole Nussbaumer Knaflic / 陆 昊、吴梦颖 / 人民邮电出版社 / 2017-8 / 59.00元

本书通过大量案例研究介绍数据可视化的基础知识,以及如何利用数据创造出吸引人的、信息量大的、有说服力的故事,进而达到有效沟通的目的。具体内容包括:如何充分理解上下文,如何选择合适的图表,如何消除杂乱,如何聚焦受众的视线,如何像设计师一样思考,以及如何用数据讲故事。一起来看看 《用数据讲故事》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具