函数定义,以及用到的关键字
doubleMe x = x + x
doubleSmallNumber x = if x > 100
then x
else x*2
Haskell 中 if
语句的 else
部分是不可省略。(表达式就是返回一个值的一段代码)
模式匹配 (Pattern matching):
- (根据类型或值)模式匹配通过检查数据的特定结构来检查其是否匹配,并按模式从中取得数据。
- 模式会从上至下进行检查,一旦有匹配,那对应的函数体就被应用了。
lucky :: (Integral a) => a -> String
lucky 7 = "LUCKY NUMBER SEVEN!"
lucky x = "Sorry, you're out of luck, pal!"
capital :: String -> String
capital "" = "Empty string, whoops!"
capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]
as
模式,就是将一个名字和
@
置于模式前,可以在按模式分割什么东西时仍保留对其整体的引用
Guards: 模式用来检查一个值是否合适并从中取值,而 guard 则用来检查一个值的某项属性是否为真。
max' :: (Ord a) => a -> a -> a
max' a b
| a > b = a
| otherwise = b
关键字 Where, Let
where
关键字跟在 guard 后面(最好是与竖线缩进一致),可以定义多个名字和函数。这些名字对每个 guard 都是可见的,这一来就避免了重复。let
绑定与where
绑定很相似。where
绑定是在函数底部定义名字,对包括所有 guard 在内的整个函数可见。let
绑定则是个表达式,允许你在任何位置定义局部变量,而对不同的 guard 不可见。let
的格式为let [bindings] in [expressions]
。在let
中绑定的名字仅对in
部分可见。let
里面定义的名字也得对齐到一列。
let
绑定本身是个表达式,而where
绑定则是个语法结构。还记得前面我们讲if语句时提到它是个表达式,因而可以随处安放?
bmiTell :: (RealFloat a) => a -> a -> String
bmiTell weight height
| weight / height ^ 2 <= 18.5 = "You're underweight, you emo, you!"
| weight / height ^ 2 <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
| weight / height ^ 2 <= 30.0 = "You're fat! Lose some weight, fatty!"
| otherwise = "You're a whale, congratulations!"
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
cylinder :: (RealFloat a) => a -> a -> a
cylinder r h =
let sideArea = 2 * pi * r * h
topArea = pi * r ^2
in sideArea + 2 * topArea
ghci> 4 * (let a = 9 in a + 1) + 2
42
Case expressions
函数参数的模式匹配只能在定义函数时使用,而 case 表达式可以用在任何地方
describeList :: [a] -> String
describeList xs = "The list is " ++ case xs of [] -> "empty."
[x] -> "a singleton list."
xs -> "a longer list."
describeList :: [a] -> String
describeList xs = "The list is " ++ what xs
where what [] = "empty."
what [x] = "a singleton list."
what xs = "a longer list."