1.模式匹配(Pattern Match)

lucky::Int->String
lucky 7 = "LUCKY NUMBER SEVEN"
lucky x = "Sorry, you are out of lucky, pal!"

*Main> lucky 7
"LUCKY NUMBER SEVEN"
*Main> lucky 8
"Sorry, you are out of lucky, pal!"

sayMe::Int->String
sayMe 1 = "One!"
sayMe 2 = "Two!"
sayMe 3 = "Three!"
sayMe 4 = "Four!"
sayMe 5 = "Five!"
sayMe x = "Not between 1 and 5!"

factorial::Int->Int
factorial 0 = 1
factorial n = n * (factorial (n-1))

charName::Char->String
charName 'a' = "Albert"
charname 'b' = "Broseph"
charName 'c' = "Cecil"

*Main> charName 'h'
"*** Exception: 01.hs:18:1-23: Non-exhaustive patterns in function charName

*Main> charName 'a'
"Albert"

2.元组与模式匹配

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)

first::(a,b,c)->a
first (x,_,_) = x
second::(a,b,c)->b
second (_,y,_) = y
third::(a,b,c)->c
third (_,_,z) = z

3.List、List Comprehension和模式匹配

let xs = [(1,3),(4,3),(2,4),(5,6),(5,3),(3,1)]
[a + b | (a,b)<-xs]

tell::(Show a) => [a]->String
tell [] = "Empty String!"
tell (x:[]) = "The list has only one element: " ++ show x
tell (x:y:[]) = "The list has two elements. First: " ++ show x ++ " Second is: " ++ show y
tell (x:y:_) = "The list has more than two elements."

4.As-Pattern

fstLetter::String->String
fstLetter ""="Empty String!"
fstLetter all@(x:_)="The first letter of " ++ all ++ " is " ++ [x]

5.Guards

bmiTell :: Double->String
bmiTell bmi
| bmi <= 18.5 = "You are underweight!"
| bmi <= 25.0 = "You are normal!"
| bmi <= 30.0 = "You are fat!"
| otherwise = "You are whale!"

Guards的语法如下：每一个Guard由一个管道符号|所标识，后跟一个Boolean表达式，后面跟着当这个表达式为True时执行的函数体。一般来说，最后一个Guard是otherwise，这个Guard匹配所有的情况，目的和catchall模式一样。在接收多个参数的函数中使用Guards也是允许的，我们让上面的函数接收两个参数，然后改写一下：

bmiTell' :: Double->Double->String
bmiTell' weight height
| weight / height ^ 2 <= 18.5 = "You are underweight!"
| weight / height ^ 2 <= 25.0 = "You are normal!"
| weight / height ^ 2 <= 30.0 = "You are fat!"
| otherwise = "You are whale!"

max'::(Ord a)=>a->a->a
max' a b
| a <= b = b
| otherwise = a

compare':: (Ord a)=>a->a->Ordering
a compare' b
| a == b = EQ
| a < b = LT
| otherwise = GT

6.where语句

bmiTell'' :: Double->Double->String
bmiTell'' weight height
| bmi <= 18.5 = "You are underweight!"
| bmi <= 25.0 = "You are normal!"
| bmi <= 30.0 = "You are fat!"
| otherwise = "You are whale!"
where bmi = weight / height ^ 2

where语句中定义的变量只会对当前的函数可见，因此不必担心它们会污染别的函数的作用域。要想定义的变量多个函数共用，则需要将这些变量定义为全局变量。where中定义的变量是不会在一个函数中的多个模式中共享的。看下面的例子：

greet :: String -> String
greet "Juan" = niceGreeting ++ " Juan!"
greet "Fernando" = niceGreeting ++ " Fernando!"
greet name = badGreeting ++ " " ++ name
where niceGreeting = "Hello! So very nice to see you,"
badGreeting = "Oh! Pfft. It's you."

badGreeting :: String
badGreeting = "Oh! Pfft. It's you."
niceGreeting :: String
niceGreeting = "Hello! So very nice to see you,"
greet :: String -> String
greet "Juan" = niceGreeting ++ " Juan!"
greet "Fernando" = niceGreeting ++ " Fernando!"
greet name = badGreeting ++ " " ++ name

initials :: String->String->String
initials firstName lastName = [f] ++ ". " ++ [l] ++ "."
where (f:_) = firstName
(l:_) = lastName

calcBMI::[(Double,Double)]->[Double]
calcBMI xs = [bmi w h|(w,h)<-xs]
where bmi weight height = weight / height ^ 2

7.let语句

let语句与where有些不同，可以在函数中任何地方定义，但是let绑定的变量非常局部，不能跨越Guard。我们看一个例子：

cylinder::Double->Double->Double
cylinder r h =
let sideArea = 2 * pi * r * h
topArea = pi * r ^ 2
in	sideArea + 2 * topArea

*Main> 4 * (let a = 9 in a + 1) + 2
42

let还可以用来定义本地函数：

*Main> [let square x = x * x in (square 5,square 3,square 4)]
[(25,9,16)]

*Main> (let a = 100; b = 200; c = 300 in a * b *c, let foo="Hey "; bar = "there!" in foo ++ bar)
(6000000,"Hey there!")

*Main> (let (a, b, c) = (1, 2, 3) in a+b+c) * 100
600

let还可以在List Comprehension中使用，我们看这个例子：

calcBMI'::[(Double,Double)]->[Double]
calcBMI' xs = [bmi|(w,h)<-xs,let bmi = w/h^2]

8.case语句

case语句和我们之前说的Guards很类似，和switch-case也很类似，我们之间可以个例子就明白了：

head''::[a]->a
head'' xs = case xs of [] -> error "Empty List!"
(x:_) -> x

case语句的格式是：

case expression of pattern -> result
pattern -> result
pattern -> result

ps：终于将博客园的代码样式换成自己喜欢的了，非常感谢@Rollen Holt

posted @ 2012-08-19 11:52  wawlian  阅读(5457)  评论(2编辑  收藏  举报