感嘆符は、Haskellの宣言では何を意味するのでしょうか?
-
13-09-2019 - |
質問
私は、次の定義に出くわしました。私は、各引数の前に感嘆符を意味し、私の本はそれを言及していないようでしたか理解していない。
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"
これは、それが必要なものを行うのに十分なコードを実行するつもりはない、とこれ以上されます。 (あなたはそれが既存せずに内部を見ることができないため)だから、四つのパラメータではFooを作成します。我々はそれをテストしているので、まず、私たちはそれが一致していません実現4
するすべての方法を、評価する必要があります。
二つ目は、我々はそれをテストしていないので、評価する必要はありません。したがって、6
は、そのメモリ位置に格納されるのではなく、私たちは、(3+3)
を可能後の評価のためのコードを格納します。それは、誰かがそれを見た場合にのみ6に変わります。
第三のパラメータが、しかし、その前に!
を有しているので、厳密に評価される:(4+4)
が実行され、そして8
はそのメモリ位置に格納されている
四番目のパラメータは、厳密に評価されます。それは少しトリッキー取得する場所しかし、ここです:我々は唯一の弱い通常のヘッドフォームに、ない完全に評価しています。これは、我々はそれがNothing
またはJust
何かかどうかを把握し、それを保存することを意味するが、我々はそれ以上行くん。それは我々が未評価の内部サンクを残し、Just 10
実際Just (5+5)
ない保存することを意味します。私はこのすべての意味ではなく、この質問の範囲を超えて行くと思いますが、これは、知っておくことが重要です。
BangPatterns
言語の拡張機能を有効にした場合、あなたは、同じように関数の引数に注釈を付けることができます:
f x !y = x*y
f (1+1) (2+2)
はサンク(1+1)*4
を返します。
他のヒント
厳格かつ非厳密コンストラクタ引数との違いを確認する簡単な方法は、彼らが定義されていないとき、彼らはどのように動作するかです。
を考えますdata Foo = Foo Int !Int
first (Foo x _) = x
second (Foo _ y) = y
非厳格な引数がsecond
によって評価されていないので、undefined
に渡しても問題は発生しません。
> second (Foo undefined 1)
1
しかし、厳格な引数は、私たちが値を使用しない場合でも、undefined
することはできません。
> first (Foo 1 undefined)
*** Exception: Prelude.undefined
私はそれは厳密注釈であると考えています。
Haskellは純粋で、の怠惰の関数型言語であるが、時にはlazynessのオーバーヘッドがあまりにも多くのか無駄にすることができます。だから、それに対処するために、あなたは完全に代わりに周りにサンクを解析する関数に引数を評価するために、コンパイラに依頼することができます。
このページについての詳細はあります:パフォーマンス/正格には、