パターンマッチとガード

関数定義の一般形

関数名 パターン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
                        :
      :
      :