読者です 読者をやめる 読者になる 読者になる

Haskell を使ってみる 6 (パターンマッチ)

前回の続き

Haskell を使ってみる 5 (型) - kntmr-blog

パターンマッチ

パターンマッチは、データ型が従うべきパターンを指定してそのパターンに従ってデータを分解するために使う。

-- パターンマッチと再帰で n の階乗を求める関数
factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial (n - 1)

*Main> factorial 5
120

パターンマッチでパターンに合致しない値を指定するとエラーになる。パターンマッチの最後にすべてに合致するパターンを入れる。

showNumber :: Int -> String
showNumber 1 = "One"
showNumber 2 = "Two"
showNumber 3 = "Three"

*Main> showNumber 1
"One"
*Main> showNumber 5 -- これはパターンにない
"*** Exception: pattern-matching.hs:(6,1)-(8,22): Non-exhaustive patterns in function showNumber
タプルのパターンマッチ

タプルの要素を分解して処理できる。

-- ペアを受け取って足し合わせる関数
addVectors :: (Int, Int) -> (Int, Int) -> (Int, Int)
addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)

*Main> addVectors (1, 2) (2, 3)
(3,5)
リストのパターンマッチ

リスト内包表記でパターンマッチを使う場合、パターンに合致しないものは処理されない。

Prelude> let xs = [(1,2), (2,3), (2,4), (1,5), (3,6)]
Prelude> [x * 100 | (1, x) <- xs] -- 1つ目の要素が1のペアのみ処理される
[200,500]
リストのパターンマッチ

リストの先頭3要素を足し合わせる関数。

sumThree :: (Num a) => [a] -> a
sumThree [] = 0
sumThree (x:[]) = x
sumThree (x:y:[]) = x + y
sumThree (x:y:z:[]) = x + y + z
sumThree (x:y:z:_) = x + y + z -- この行がないと4要素のリストを指定した場合にエラーになる

*Main> sumThree []
0
*Main> sumThree [1]
1
*Main> sumThree [1, 2]
3
*Main> sumThree [1, 2, 3]
6
*Main> sumThree [1, 2, 3, 4] -- 4つ目の要素は足し合わされない
6
as パターン

as パターンでは、パターンマッチの対象になる値自体を参照することができる。パターンの前に名前と @ を付ける。

firstLetter :: String -> String
firstLetter "" = "Emptry string."
firstLetter all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]

*Main> firstLetter ""
"Emptry string."
*Main> firstLetter "Hello"
"The first letter of Hello is H"

今回はパターンマッチについて。