14

Haskell の定義は次のように述べています。

次のいずれかの場合、式は弱主正規形 (WHNF) です。

  • True、Just (square 42)、(:) 1 などのコンストラクター (最終的に引数に適用される)
  • (+) 2 や sqrt のように、あまりにも少ない引数 (おそらくなし) に適用される組み込み関数。
  • またはラムダ抽象 \x -> 式。

組み込み関数が特別な扱いを受けるのはなぜですか? ラムダ計算によれば、部分的に適用された関数と他の関数との間に違いはありません。これは、最後に引数関数が 1 つしかないためです。

4

2 に答える 2

22

次のように、引数に適用される通常の関数:

(\x y -> x + 1 : y) 1

を与えるために減らすことができます:

\y -> 1 + 1 : y

最初の式では、「最も外側」のものはアプリケーションだったので、WHNF にはありませんでした。2 番目に、最も外側のものはラムダ抽象化であるため、WHNF にあります (関数本体内でさらに削減を行うことはできますが)。

ここで、組み込み (プリミティブ) 関数の適用を考えてみましょう。

(+) 1

1これは組み込みであるため、最初のパラメーターを置き換えることができる関数本体はありません。(+)評価者は、 などの の完全に「飽和した」アプリケーションを評価する方法を「知っている」だけ(+) 1 2です。しかし、部分的に適用されたビルトインでできることは何もありません。「(+) を 1 に適用し、もう 1 つの引数を待つ」というデータ構造を作成することしかできませんが、削減しようとしているのはまさに. だから私たちは何もしません。

ビルトインは、ラムダ計算式で定義されていないため特別です。そのため、リダクション プロセスはそれらの定義の「内部を見る」ことができません。したがって、通常の関数アプリケーションとは異なり、組み込み関数アプリケーションは、完全に「飽和」するまで引数を蓄積するだけで「縮小」する必要があります (この場合、WHNF への縮小は、組み込みの魔法の実装が何であれ実行することによって行われます)。 . 飽和していないビルトイン アプリケーションはこれ以上減らすことができないため、既に WHNF に含まれています。

于 2014-06-27T09:02:21.193 に答える
3

検討

プレリュード> let fn = [(+x) | x <- [1..]] !! n
Prelude> let g = f 20000000 :: Int -> Int

gこの時点では、WHNF にはありません。g 3これは、引数を適用する前に WHNF が必要なため、たとえば を評価することで確認できます。それは、適切な組み込み関数を検索するためにリストがトラバースされるときです。しかし、その後、この選択は修正され、gWHNF (実際には NF: ラムダについても同じです。おそらく、質問で意味したことです) であるため、後続の呼び出しはすぐに結果を返します。

于 2014-06-27T08:56:46.097 に答える