Haskell 笔记(四)函数系统

时间:2023-03-09 10:01:30
Haskell 笔记(四)函数系统

函数系统


函数式编程当然少不了函数系统啦,在教程最初的时候就有一个最简单的函数,函数系统贯穿在Haskell全部,Haskell的函数有几个重要的性质。

  • 首先声明一下函数的参数和返回值类型
  • 然后有一个很重要写法就是匹配,用匹配来匹配参数,所以Haskell的函数写法和其他语言不一样,同样一个函数可能有几种表达形式

模式匹配


函数匹配的一个例子,比如有这么一个函数,当用户输入7时显示输入了七,否则显示没输入7.

lucky :: (Integral a) => a -> String
lucky 7 = "LUCKY NUMBER SEVEN!"
lucky x = "Sorry, you're out of luck, pal!"
  • 第一行表示参数是个数字,输出是个字符串
  • 模式匹配自上向下检查匹配结果
  • 当匹配上以后就运行匹配项的函数并且后面的不会进行匹配

Guards


Guard,直译过来就是守卫,简单的说就是if语句,这是一个比模式匹配更精确的定位方式,可以更加精确的确定参数范围。

bmiTell :: (RealFloat a) => a -> String
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!"
  • 使用|表示守卫
  • 一个 guard 就是一个布尔表达式,如果为真,就使用其对应的函数体。如果为假,就送去见下一个 guard
  • 使用otherwise表示任意其他情况

Where


Where用来在函数中绑定变量的数值,一般写在函数的最后面,比如上一个例子中的bmi,如果使用身高和体重计算出来的话,可以写成Where形式。

bmiTell :: (RealFloat a) => a -> a -> String
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!"
where bmi = weight / height ^ 2
  • Where关键字中的变量只在函数中有效,不会污染命名空间
  • 绑定不会在多个模式*享。如果你在一个函数的多个模式中重复用到同一名字,就应该把它置于全局定义之中

Let


let 绑定与 where 绑定很相似。where 绑定是在函数底部定义名字,对包括所有 guard 在内的整个函数可见。let 绑定则是个表达式,允许你在任何位置定义局部变量,而对不同的 guard 不可见

看一个依据半径和高度求圆柱体表面积的函数

cylinder :: (RealFloat a) => a -> a -> a
cylinder r h =
let sideArea = 2 * pi * r * h
topArea = pi * r ^2
in sideArea + 2 * topArea
  • let 的格式为 let [bindings] in [expressions]
  • let 绑定本身是个表达式,而 where 绑定则是个语法结构
  • 在 let 中绑定的名字仅对 in 部分可见
本教程参考了《Haskell趣学指南》,是这篇指南的学习笔记,不过参入了我自己的一些想法和总结,首先,感谢《Haskell趣学指南》的作者bonus 和大陆翻译者Fleurer和*翻译者MnO2,谢谢你们之前的工作。