パターンマッチとガード
関数定義の一般形
関数名 パターンA1 パターンA2 ... | ガードA1 = 定義A1 | ガードA2 = 定義A2 | ガードA3 = 定義A3 : 関数名 パターンB1 パターンB2 ... | ガードB1 = 定義B1 | ガードB2 = 定義B2 | ガードB3 = 定義B3 : : :
一つの関数は複数の引数を持ち、各引数をパターンで受け、さらにパターンごとにガードで絞り込み、対応する動作を定義をする。
パターン
- 変数パターン
- id x = x
- 任意の値にマッチし、その値に変数を束縛する
- ワイルドカード "_"
- map _ [ ] = [ ]
- 任意の値にマッチするが、その値を使わない
- リテラルパターン
- タプルパターン
- format (n, line) = rjust 6 (show n) ++ " " ++ line
- (パターン1, パターン2, パターン3, ...)
- リストパターン
- last [x] = x
- [パターン1, パターン2, パターン3, ...]
- データコンストラクタパターン
- map _ =
- map f (x: xs) = f x : map f xs
- asパターン
- lstrip str@(c: cs) = if isSpace c then lstrip cs else str
- 変数名@パターン
- OCaml の as とは順番が逆
- 値全体と部分の両方を使いたいときに便利
- n+kパターン
- f (n+3) = n*2
- kは定数
- k以上の整数にマッチし、nを(マッチした数 - k) に束縛する
- 遅延パターン
- f ~(x: xs) = xs
- マッチは必ず成功する
- 関数適用時にはまだ値が確定していない場合に使う
- その値が評価されるとき初めて値を束縛する
ガード
- 引数列と = の間に | で区切って引数の条件を書く
- パターンマッチと合わせて使い、任意のBool型の式が使える。
- 例) f [x] | x > 0 = 1
case式
- 任意の式に対してパターンマッチとガードが使える。
- case式自体が値を持つ
- of の後ろはコードブロック(各パターンのインデントを揃える or { ; }を使う)
case 式 of パターンA | ガードA1 -> 式A1 | ガードA2 -> 式A2 : パターンB | ガードB1 -> 式B1 | ガードB2 -> 式B2 : パターンC | ガードC1 -> 式C1 | ガードC2 -> 式C2 : : :