系列文章緩存
寫好模式,Haskell 會直接幫你匹配。如:函數
lucky :: Int -> String
lucky 7 = "7 is the lucky number!"
lucky x = "sorry, you are not lucky"
複製代碼
載入以後運行post
λ> 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 了。spa
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)
中的 all 表示整個 x:items 列表,方便後面引用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,就會進入下一個模式。3d
可使用 where 來對計算結果進行緩存,也能夠定義其餘的幫助函數:code
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 只在當前模式中有效。ci
就算沒有 guard,也能夠在函數定義中使用 where:get
calcBmis :: [(Double, Double)] -> [Double]
calcBmis xs = [bmi w h | (w, h)< - xs]    
where bmi weight height = weight / height ^ 2
複製代碼
what 還能這樣用string
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 函數。it
ghci> 4 * (let a = 9 in a + 1) + 2
42
複製代碼
let 和 where 類似,不一樣點在於 where 只容許咱們在函數底部綁定變量,且對當前模式可見。而 let 能夠出如今任何地方,且 let 裏面的變量只在 in 內有效。
另外一個區別就是 let 是表達式(有值),而 where 不是。
case <exp> of pattern1 -> result1
pattern2 -> result2
pattern3 -> result3
複製代碼
模式匹配不過是 case 的語法糖,並且模式匹配只能用在函數定義裏,而 case 能夠用在任何地方。