問題タブ [weak-head-normal-form]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
haskell - ウィークヘッドノーマルフォームとは何ですか?
ウィークヘッドノーマルフォーム(WHNF)とはどういう意味ですか?ヘッドノーマルフォーム(HNF)とノーマルフォーム(NF)はどういう意味ですか?
実世界のハスケルは次のように述べています。
おなじみの 関数は、式をヘッドノーマルフォーム (略してHNF)
seq
と呼ぶものに評価します 。最も外側のコンストラクター(「ヘッド」)に到達すると停止します。これは、式が完全に評価される正規形 (NF)とは異なり ます。また、Haskellプログラマーがウィーク ヘッドノーマルフォーム(WHNF)を参照しているのを聞くでしょう 。通常のデータの場合、弱い頭の通常の形式は頭の通常の形式と同じです。違いは関数に対してのみ発生し、ここで私たちを気にするのはあまりにも厄介です。
いくつかのリソースと定義(HaskellWikiとHaskellメールリストと無料辞書)を読みましたが、わかりません。誰かが例を挙げたり、素人の定義を提供したりできますか?
私はそれが次のようになると推測しています:
WHNFとHNFとどのようseq
に関係していますか?($!)
アップデート
私はまだ混乱しています。私はいくつかの答えがHNFを無視すると言っていることを知っています。さまざまな定義を読むと、WHNFとHNFの通常のデータに違いはないようです。ただし、関数に関しては違いがあるように見えます。違いがなかったのなら、なぜseq
必要なのfoldl'
ですか?
もう1つの混乱のポイントは、Haskell Wikiからのものです。これは、seq
WHNFに還元され、次の例には何もしません。それから彼らは彼らがseq
評価を強制するために使用しなければならないと言います。それはそれをHNFに強制していませんか?
一般的な初心者スタックオーバーフローコード:
seqとweakheadnormal form(whnf)を理解している人は、ここで何が悪いのかをすぐに理解できます。
(acc+x, len+1)
はすでにwhnfにあるので、 値をwhnfに減らすseq
(の定義内のfoldl'
)はこれに対して何もしません。このコードは、元の例と同じようにサンクを構築しfoldl
ます。それらはタプルの中にあります。解決策は、タプルのコンポーネントを強制することです。
--StackoverflowのHaskellWiki
performance - Haskell foldl' (++) でのパフォーマンスの低下
私はこのコードを持っています:
これらの関数は、各要素に 2 を掛けたリストを返します。
ghci で:
newList_bad
関数の動作が の 200 倍遅いのはなぜnewList_good
ですか? それがそのタスクの良い解決策ではないことを理解しています。しかし、なぜこの無害なコードの動作がこれほど遅いのでしょうか?
この「4767099960バイト」とは何ですか?? その単純な操作のために、Haskell は 4 GiB を使用しました??
コンパイル後:
haskell - 弱頭の正常な形と評価の順番
私は弱い頭の通常の形と配列についてたくさん読んだ。しかし、Haskell の評価順序の背後にあるロジックを想像するのはまだ難しい
いつ、どのように使用するかを示す一般的な例ですが、一般的な例がどのように使用されるかはまだわかりません
スタック オーバーフローが発生する可能性があります。を使用した別の折り畳み定義seq
はそうではありませんが
私が読んだ seq の説明から、著者は次のことを明確にするために非常に注意を払っています:
- の最初の引数は
seq
、2 番目の引数の前に評価されるとは限りません - の最初の引数は、
seq
弱頭正規形にのみ評価されます - の最初の引数の評価は、
seq
2 番目の引数が WHNF に評価される場合にのみ発生します。
では、上記が正しければ (そうですか?)、なぜfoldl'
のようにオーバーフローしないのfoldl
でしょうか?
一歩減らすとこうなるじゃないですか。
上記では、実行する必要がある関数適用があるため、の 2 番目の引数はseq
WHNF にありません。seq
2 番目の引数の WHNF に到達する前に、hereの最初の引数を評価することが保証されていますか?
haskell - 組み込み関数があまりにも少ない引数に適用されると、弱い頭部正規形であると見なされるのはなぜですか?
Haskell の定義は次のように述べています。
次のいずれかの場合、式は弱主正規形 (WHNF) です。
- True、Just (square 42)、(:) 1 などのコンストラクター (最終的に引数に適用される)
- (+) 2 や sqrt のように、あまりにも少ない引数 (おそらくなし) に適用される組み込み関数。
- またはラムダ抽象 \x -> 式。
組み込み関数が特別な扱いを受けるのはなぜですか? ラムダ計算によれば、部分的に適用された関数と他の関数との間に違いはありません。これは、最後に引数関数が 1 つしかないためです。
haskell - GHCi let 束縛が関与するときのサンクの異なる振る舞いを理解する
Haskell での並列および並行プログラミングに関する Simon Marlow の本からいくつかの例を試してみたところ、よくわからない興味深い動作に出くわしました。これは、GHC の内部動作のいくつかを理解しようとしている私に関するものです。
REPLで次のことをするとしましょう:
z がすでに WHNF に評価されていることを除けば、これは私が予想したこととほぼ同じです。同様のプログラムを作成して、ファイルに入れましょう。
GHCiでそれをいじります:
したがって、これは少し異なる動作をします:z
事前に WHNF に評価されません。私の質問は:
ファイルから定義をロードするときではなく、z
行うときに REPL で WHNF に評価されるのはなぜですか。let z = (x,x)
私の疑惑は、それがパターンバインディングと関係があるということですが、明確にするためにそれをどこで調べたらよいかわかりません (完全に間違っているかもしれません)。ファイルの例のように何らかの形で動作することを期待していました。
なぜこれが起こるのか、ポインタや簡単な説明はありますか?
haskell - Haskell がラムダ抽象化を Weak Head Normal Form (WHNF) と見なすのはなぜですか?
Haskell では、ラムダは WHNF にあると見なされますが、適用されていないユーザー定義関数はそうではありません。この違いの背後にある動機は何でしたか?
haskell - 値が弱頭正規形に評価されているかどうかをテストします
Haskellでは、値が弱い頭の正規形に評価されているかどうかをテストすることは可能ですか? 関数が既に存在する場合、次のような署名があると予想されます
同様の機能が存在する場所がいくつかあります。
以前の回答で ghci コマンドを紹介されました。:sprint
このコマンドは、すでに弱いヘッドの通常の形式に強制されている値の部分のみを出力します。:sprint
値が評価されたかどうかを観察できます。
IO
そうでなければ立ち入り禁止のプロパティを調べることができます。たとえば、IO
2 つの値が同じ宣言に由来するかどうかを比較することができます。これは の によって提供され、StableName
data -reifySystem.Mem.StableName
で観察可能な共有の問題を解決するために有名に使用されます。関連は、参照された値が弱いヘッドの正規形であるかどうかをチェックするメカニズムを提供しません。StablePtr
haskell - WHNF でラムダ式を減らす
次のラムダ式を WHNF に縮小する必要がありますが、その方法がよくわかりません。
それで、どうすればいいですか?名前呼びの削減?
この表現(他の例)(λz x. (λx. x) z) x
はWHNFにまだありますか?