《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 可以用在任何地方。


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

查看所有标签

猜你喜欢:

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

How to Design Programs, 2nd Edition

How to Design Programs, 2nd Edition

Matthias Felleisen、Robert Bruce Findler、Matthew Flatt、Shriram Krishnamurthi / MIT Press / 2018-5-4 / USD 57.00

A completely revised edition, offering new design recipes for interactive programs and support for images as plain values, testing, event-driven programming, and even distributed programming. This ......一起来看看 《How to Design Programs, 2nd Edition》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具