技術のメモ箱

Haskell/パターンマッチ

パターンマッチ

引数の構造・値によって関数を別々に定義できる。
パターンが網羅的でなくてもコンパイルは通るが、合致しないパターンが入力されるとエラーとなる。
オプションを設定すればコンパイラに警告を出してもらうこともできる。

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

パターンに小文字の名前(変数)を書けば任意の値と合致する。引数はその変数に束縛される。
なお_は使われない変数を表す。予約語のため通常の変数としては使えない。
以下は階乗を計算する再帰的な関数。

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

タプルのパターンマッチ

タプルの要素に適切な名前を付けることができる。

add :: (Int, Int) -> Int
add (x, y) = x + y

リスト内包表記のパターンマッチ

リスト内包表記ではマッチしなかったら単に次の要素に進む。

Prelude> [x + 10 | (x, 3) <- [(1,3),(2,1),(4,3),(2,3)]]
[11,14,12]

リストのパターンマッチ

(x:xs)というパターンは、リストの先頭要素をxに束縛し、リストの残りをxsに束縛する。
(x:[])は[x]と等しく、(x:y:[])は[x,y]と等しい。しかし、(x:y:_)に対応する角括弧の書き方はない。

headMe :: [a] -> a
headMe [] = error "empty list"
headMe (x:_) = x

asパターン

パターンに分解した値の、元の値自体を参照したいときに使う。
パターンの前に名前と@を付けることで参照できる。

firstLetter :: String -> String
firstLetter "" = "empty String"
firstLetter all@(x:_) = "The first letter of " ++ all ++ " is " ++ [x]
pagetop