2017-01-08 5 views
0

ハスケルのような遅延プログラミング言語の正確な型が何であるか知りたい。遅延評価におけるプリミティブ関数のタイプ

ここで、サンクは弱い頭の通常の形のオブジェクトに評価されています。次に、Cのような厳密な言語でのプリミティブ関数の型はどうでしょうか?

私の推測は、次のとおりです。

primitive1 : (thunk, thunk, ...) -> thunk 
primitive2 : (thunk, thunk, ...) -> object 

私は、彼らがそれらのいくつかを必要としないかもしれないので、プリミティブ関数は、引数としてサンクを渡すべきだと思います。しかし、私は彼らがサンクや評価されたオブジェクトを返す必要があるかどうかはわかりませんが、遅いものは以下のようないくつかの関数でラップして怠け者にする必要があります。 GHC、Haskellの原始関数(時々PrimOpと呼ばれる)(「ヒープ・オブジェクト」)はポインタの混合物と呼ば であり、(Cスタイルのint値を含む、ダブルス、など)非ボックス化 タイプで

lazy : ((thunk, thunk, ...) -> object) -> ((thunk, thunk, ...) -> thunk) 
+1

実装に依存するので、この質問に対する一意の答えはありません。 ghcでは、プリミティブ演算はプリミティブ型を持ちます。C言語と同じ型です。プリミティブ型をサンクでラップアンドアンラッピングするための別の操作があります。 – augustss

+0

@augustss ifとcase式はどうですか?彼らのプリミティブはサンクスに直接渡されなければなりません。または、彼らはカレーですか? – raviqqe

+0

if式がcase式に変換されます。また、プリミティブがない場合は、型に依存する(抽象的な)マシンコードに変換されます。簡略化された最初のscrutineeはWHNFに評価され、次にコンストラクタ番号を抽出してジャンプテーブルのオフセットとして使用します。ジャンプするコードは、コンストラクタのフィールドを展開し、評価を続行します。 – augustss

答えて

1

。 Haskellタイプのシステム は、PrimOpsがいつも期待しているポインタとボックス化されていない値の数、順序、タイプを取得することを保証します。これは、プリミティブがヒープオブジェクトの特定の型へのポインタを期待しているところ、Stringは、 それがあるため(いずれかリスト コンストラクタかもしれヒープオブジェクトへのポインタを期待していると言うこと、しかし、注意することが を重要ですHaskell Stringは文字のリストですまたはサンク リストコンストラクタで評価することができます。

したがって、Haskell PrimOpの「厳密な」タイプは、サンクと非サンクの間で を区別しません。原始関数が にあった場合は、リストの長さは、例えば(ありません)を取得、それはおそらく、あなたの表記を使用して、タイプを持つことになり、の:

list_objectへのポインタになり
primitiveLength : (list_object) -> unboxed_int 

リスト コンストラクタまたはリストコンストラクタを生成できるサンク。

これは本当に賢明なアプローチです。 PrimOpは、その引数がまだサンクであるか、以前の計算によって部分的に(または完全に)評価されたかどうかを制御することができないので、どちらかを受け入れる準備ができている必要があります。

同様に、Haskell PrimOp がヒープオブジェクトを返す場合、そのオブジェクトは技術的にサンクでも非サンクでもかまいません。その選択はプリミティブの "厳密な"型シグネチャには影響しません。

実際には、PrimOpがサンクを返すのはあまり役に立ちません。レイジー言語では、プリミティブが呼び出されているという事実は、その戻り値が必要であることを意味します。それがサンクを返す場合、そのサンクはすぐに評価する必要があります、なぜサンクを返すのですか?

(追加編集:)ところで、上記のPrimOpsには本当に特有のものはありません。ユーザー定義のHaskell関数も、ポインタとボックス化されていない型の混合で呼び出されます(そして、サンクを返すことはありません)。

+0

プリミティブ関数でサンクの作成と評価の両方が可能ですか? – raviqqe

+0

プリミティブ*はサンクを評価できますが、ほとんど行いません。たとえば、 'newArray#'はサンク(配列要素の初期値)を取ることができますが、評価しません - サンクへのポインタで配列を取り込むだけです。私は 'raise#'がサンクを受け入れる(そして評価する)プリミティブの例だと思います。サンクを評価することは新しいサンクを作り出すことができるので、これは 'raise#'がサンクを暗黙的に*作成できることを意味します。明示的にサンクを作成するプリミティブについてはわかりませんが、プリミティブはヒープオブジェクトを作成でき、サンクは別のヒープオブジェクトにすぎないため、なぜできないのかわかりません。 –

+0

@raviqqe、サンクを作成できる1つのプリミティブは、 'tryTakeMVar#:: MVar#s a - > State#s - >(#State#s、Int#、a#)'です。 'MVar'が空の場合、それは未定義の値(強制的にエラーを生成するサンク)を返します。 'tryReadMVar#'についても同様です。これは文書化されていませんが、誰かがキーが収集されたウィークポインタを間接参照しようとすると、 'deRefWeak#'の場合と同じように見えます。 – dfeuer