or1ko's diary

日々を書きます

:(コロン)演算子の定義と~(チルダ)演算子の話

今日、:(コロン)演算子Preludeにあるかと思って探したけれどなかったので、調べた。

コロンそのもの ":" は Haskell のリスト構築子専用に予約され ていることに注意すること
Haskell 98 Lexical Structure

:(コロン)って予約されてたんだ。$(ドル)や.(ピリオド)と同じようにPreludeで宣言されているのかと思ってた。

ついでに、他の予約されている演算子を調べた。

reservedop -> .. | : | :: | = | \ | | | <- | -> | @ | ~ | =>
Haskell 98 Lexical Structure

\と@と~も知らな...いや、@はアズパターンだ。それに\は∖だ。

残る~は、さっぱり分からない。ので調べてみたところ...、この演算子はやばい気配がすることが分かった。反駁って何\(^o^)/

...(10分ほど経過)

やっとわかった。以下のページの定義を何度も読んだ。

2.値 v に対するパターン ~apat の照合は常に成功する。v の apat への照合が成功すれば、 apat 中の自由変数は対応する値に束縛される。もし、v の apat への照合が失敗するか、発散すれば、apat 中の自由 変数は _|_ に束縛される。(束縛は評価を強制しない)。

操作的にいえば、パターン ~apat 上の照合は、パターン apat 中の変数のひとつが使用されるまでは起こらないということ である。使用の時点でパターン全体がその値に照合され、もし、照合が失 敗あるいは発散すれば、計算全体が失敗あるいは発散する。

The Haskell 98 Report: Expressions

コードを書いてみる。まずは、~を使わない例。

Prelude> let f [x] = 0
Prelude> f []
*** Exception: <interactive>:1:4-13: Irrefutable pattern failed for pattern [x]

これは、[x]パターンの照合が成功せずに、エラーを返す。次にチルダを使った例を書く。

Prelude> let f ~[x] = 0
Prelude> f []
0

これだと~[x]パターンの照合に成功し、式fの値を返す。最後は式の右辺を変更した例。

Prelude> let f ~[x] = x
Prelude> f []
*** Exception: <interactive>:1:4-13: Irrefutable pattern failed for pattern [x]

~[x]パターンの照合には成功するものの、その後にxが評価され、[x]パターンの照合が行われる。[x]パターンの照合は失敗し、xが_|_に束縛(_|_はエラーを表す)され、xつまりエラーが評価され表示される。

たぶん、この考えでよさそう。ちなみに、~を用いたパターンを反駁不可能(irrefutable)パターン(遅延パターンとも呼ぶみたい)、用いてないものを反駁可能(refutable)パターンと呼ぶとのこと。~をつけることで、その入力じゃパターンと合わない(反駁)と言わせないよう(不可能)にしてるのかな。

それで実際にこの表記を使うような場面は、以下のURLであるような、パターンの照合を遅らせたいような場合らしい。

う〜ん、使いこなせるのだろうか\(^o^)/。