在Haskell的函数创建中,不能使用tab作为缩进,只能使用space作为缩进。
lucky :: (Integral a) => a -> String
lucky 7 = "LUCKY NUMBER SEVEN!"
lucky x = "Sorry, you're out of luck, pal!"
在调用
lucky 时,模式会从上至下进行检查,一旦有匹配,那对应的函数体就被应用了。这个模式中的唯一匹配是参数为 7
,如果不是
7
,就转到下一个模式,它匹配一切数值并将其绑定为
x
。
函数有先后顺序
sayMe :: (Integral a) => a -> String
sayMe 1 = "One!"
sayMe 2 = "Two!"
sayMe 3 = "Three!"
sayMe 4 = "Four!"
sayMe 5 = "Five!"
sayMe x = "Not between 1 and 5"
注意下,如果我们把最后匹配一切的那个模式挪到最前,它的结果就全都是
"Not between 1 and 5" 了。因为它自己匹配了 一切数字,不给后面的模式留机会。
函数有先后顺序
还有个东西叫做
as
模式,就是将一个名字和
@ 置于模式前,可以在按模式分割什么东西时仍保留对其整体的引用。如这 个模式
xs@(x:y:ys)
,它会匹配出与
x:y:ys
对应的东西,同时你也可以方便地通过
xs
得到整个
List,而不必在函数体中 重复
x:y:ys
。看下这个
quick and dirty
的例子:
capital :: String -> String
capital "" = "Empty string, whoops!"
capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]
ghci> capital "Dracula"
"The first letter of Dracula is D"
不可以在模式匹配中使用 ++。
在模式匹配中,特别函数,需要给明类型。
Guard
guard
由跟在函数名及参数后面的竖线标志,通常他们都是靠右一个缩进排成一列。一个
guard 就是一个布尔表达式,如果 为真,就使用其对应的函数体。如果为假,就送去见下一个
guard
,如之继续。
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!"
Where
我们的 where 关键字跟在 guard 后面(最好是与竖线缩进一致),可以定义多个名字和函数。这些名字对每个 guard 都是可见的,这一来就避免了重复。
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
示例:
initials :: String -> String -> String
initials firstname lastname = [f] ++ ". " ++ [l] ++ "."
where (f:_) = firstname
(l:_) = lastname
ghci> initials "white" "jackson"
"w. j."
通过模式匹配计算bmi:
calcBmis :: (RealFloat a) => [(a, a)] -> [a]
calcBmis xs = [bmi w h | (w, h) <- xs]
where bmi weight height = weight / height ^ 2
ghci> calcBmis [(75,1.85)]
[21.913805697589478]
ghci> calcBmis [(75,1.85), (70,1.85)]
[21.913805697589478,20.45288531775018]