1. ホーム

[解決済み】Haskellの宣言におけるエクスクラメーションマークの意味とは?

2022-03-31 06:23:57

質問

実際のプロジェクトを使ってHaskellを学ぼうとしたところ、次のような定義に出会いました。 各引数の前にある感嘆符の意味がわからないのですが、私の本では触れていないようです。

data MidiMessage = MidiMessage !Int !MidiMessage

解決方法は?

厳密性宣言です。基本的には、データ構造の値を生成するときに、いわゆる "弱いヘッド正規形" に評価されなければならないことを意味します。この意味を理解するために、例を見てみましょう。

data Foo = Foo Int Int !Int !(Maybe Int)

f = Foo (2+2) (3+3) (4+4) (Just (5+5))

機能 f つまり、その値を知るために実行すべきコードです。この時点では、Fooはまだ存在せず、コードだけです。

しかし、ある時点で誰かがその内部を見ようとするかもしれない。おそらくパターン・マッチによって。

case f of
     Foo 0 _ _ _ -> "first arg is zero"
     _           -> "first arge is something else"

これは、必要なことを行うのに十分なコードを実行し、それ以上のことは行いません。つまり、4つのパラメータを持つFooを作成します(存在しないと中を見ることができないからです)。最初のパラメータは、テストするため、すべて 4 ここで、一致しないことに気づきます。

2番目はテストしないので評価する必要はない。したがって 6 をそのメモリに保存して、後で評価できるようにコードを保存するだけです。 (3+3) . これは、誰かが見て初めて6になるのです。

しかし、第3パラメータには ! の前にあるため、厳密に評価されます。 (4+4) が実行され 8 がそのメモリ位置に格納される。

4番目のパラメータも厳密に評価される。しかし、ここで少し厄介なことがあります。完全な評価ではなく、弱い正規の先頭形式のみを評価しているのです。つまり、それが Nothing または Just のようなものがあって、それを保存しておくのですが、それ以上のことはしません。つまり Just 10 でなく、実際に Just (5+5) で、中のサンクは評価されないままです。これは知っておくべき重要なことですが、その意味するところは、この質問の範囲を超えていると思います。

を有効にすると、同じように関数の引数にアノテーションを付けることができます。 BangPatterns 言語拡張です。

f x !y = x*y

f (1+1) (2+2) はサンクを返します。 (1+1)*4 .