6

私は現在、実装機能言語: SPJ によるチュートリアルを読んでおり、この質問で参照する (サブ) 章は 3.8.7 (136 ページ) です。

最初の注意点は、チュートリアルを読んでいる読者は、ECase 式の C スキームのコンパイル (つまり、厳密ではないコンテキストに現れる式) をまだ実装していないということです。
提案された解決策は、ECase 式が非厳密なコンテキストに表示されないように Core プログラムを変換することです。具体的には、そのような出現ごとに、本体が元の ECase 式に対応する正確に 1 つの変数を持つ新しいスーパーコンビネーターが作成され、出現自体がそのスーパーコンビネーターの呼び出しに置き換えられます。以下に、 1
からのそのような変換の (少し変更された) 例を示します。

t a b = Pack{2,1} ;
f x = Pack{2,2} (case t x 7 6 of
    <1> -> 1;
    <2> -> 2) Pack{1,0} ;
main = f 3

== transformed into ==>

t a b = Pack{2,1} ;
f x = Pack{2,2} ($Case1 (t x 7 6)) Pack{1,0} ;
$Case1 x = case x of
    <1> -> 1;
    <2> -> 2 ;
main = f 3

このソリューションを実装しましたが、魅力的に機能します。つまり、出力はPack{2,2} 2 Pack{1,0}.
しかし、私が理解できないのは、なぜそんなに面倒なのかということです。私だけではないことを願っていますが、問題を解決するために最初に考えたのは、C スキームで ECase 式のコンパイルを実装することでした。そして、Eスキームのコンパイルのルールを模倣してそれを行いました(134ページですが、完全を期すためにここでそのルールを提示します):したがって、使用しました

E[[case e of alts]] p = E[[e]] p ++ [Casejump D[[alts]] p]

と書いた

C[[case e of alts]] p = C[[e]] p ++ [Eval] ++ [Casejump D[[alts]] p]

Eスキームとは対照的に、Weak Head Normal Form(WHNF)のスタックの一番上に引数が必要であり、Cスキームはそれを保証しない[Eval]ため、追加しました。Casejump

しかし、その後、出力は enigmatic: に変わりますPack{2,2} 2 6
Eスキームと同じルールを使用する場合、同じことが当てはまります。

C[[case e of alts]] p = E[[e]] p ++ [Casejump D[[alts]] p]

したがって、私の「明白な」解決策は本質的に間違っていると思います-そして、出力からそれを見ることができます。しかし、なぜそのアプローチが失敗するにちがいないのかについて、正式な議論を述べるのに苦労しています。
単純なアプローチが機能しない理由について、誰かがそのような議論/証拠またはいくつかの直感を私に提供できますか?

4

1 に答える 1