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

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

内容简介:写好模式,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 可以用在任何地方。


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

查看所有标签

猜你喜欢:

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

刷屏

刷屏

[美] 凯文•阿洛卡 / 侯奕茜、何语涵 / 中信出版社 / 2018-10-1 / 68.00

1. YouTube流行趋势经理,解密如何打造爆款视频 在视频时代,制造互动,才能创造潮流 用户不再是被动的观众,而是主动的传播者 2. 《刷屏》以行内人视角解读: 病毒视频 粉丝经济 网红产业 平台如何为内容创作者赋能 3. 你是否常常被病毒视频刷屏?你是否觉得很多网红火爆到“无法用常理解释”? 视频时代已经到来,我们每天观看网络......一起来看看 《刷屏》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具