16

GHC.Prim のモジュールを調べたところ、GHC.Prim のすべてのデータはのdata Float#ようなものなしで定義=A|Bされ、GHC.Prim のすべての関数は として定義されているようgtFloat# = let x = x in xです。

私の質問は、これらの定義が理にかなっているかどうか、およびそれらが何を意味するかです。

以下のように GHC.Prim のヘッダーを確認しました

{-
This is a generated file (generated by genprimopcode).
It is not code to actually be used. Its only purpose is to be
consumed by haddock.
-}

質問と何らかの関係があると思いますが、誰がそれを説明してくれますか。

4

2 に答える 2

25

魔法です :)

これらは「基本的な演算子と操作」です。それらはコンパイラに組み込まれているため、プリミティブ用のデータ コンストラクタはなく、純粋な haskell では必ずしも表現できないため、すべての関数は一番下にあります。

(Bottom は Haskell プログラムの「穴」、無限ループを表しているか、Bottom のundefined例です)

別の言い方をすれば

これらのデータ宣言/関数は、生のコンパイラ内部へのアクセスを提供するためのものです。GHC.Prim はこれらのプリミティブをエクスポートするために存在しますが、実際にはそれらを実装していません (たとえば、そのコードは実際には役に立ちません)。これらはすべてコンパイラで行われます。

これは、非常に最適化する必要があるコードを対象としています。あなたがそれを必要とするかもしれないと思うなら、GHCのプリミティブに関するいくつかの有用な読み物

于 2013-04-09T04:54:48.963 に答える
10

jozefgの答えの簡単な拡張...

Primops は、まさにランタイムによって提供される操作です。言語内で定義できないためです (または、効率上の理由からそうすべきではありません)。の真の目的はGHC.Prim何かを定義することではなく、Haddock がその存在を文書化できるようにいくつかの操作をエクスポートすることです。

この構造let x = x in xは、GHC のコードベースのこの時点で使用されます。これは、値undefinedがまだ「定義」されていないためです。let(それは Prelude まで待ちます。) しかし、 のような循環構造undefinedは、構文的に正しく、任意の型を持つことができることに注意してください。つまり、そのまま⊥の意味を持つ無限ループundefinedです。

...そして余談

let x = z in yまた、一般的に Haskell 式は「変数xを式のzどこにでもあるx式に変更する」ことを意味することに注意してくださいy。ラムダ計算に精通している場合は、これがラムダ抽象化\x -> yを用語 に適用するための簡約規則であることに気付くはずzです。では、Haskell 式let x = x in xは、純粋なラムダ計算の上にある構文にすぎないのでしょうか? 見てみましょう。

まず、Haskell の let 式の再帰性を説明する必要があります。ラムダ計算では再帰的な定義は認められませんが、基本的な固定小数点演算子1fixが与えられると、再帰性を明示的にエンコードできます。たとえば、Haskell 式は と同じ意味を持ちます。2 (アプリケーションの右側にある の名前を に変更して、ラムダの内部との暗黙の関係がないことを強調しました)。let x = x in x(fix \r x -> r x) zxzx

固定小数点演算子 の通常の定義を適用すると、fix f = f (fix f)の変換は次のlet x = x in xように減少します (むしろ減少しません)。

(fix \r x -> r x) z                 ==>
(\s y -> s y) (fix \r x -> r x) z   ==>
(\y -> (fix \r x -> r x) y) z       ==>
(fix \r x -> r x) z                 ==>   ...

したがって、言語の開発のこの時点で、組み込みの固定小数点演算子を使用した (型付き) ラムダ計算の基礎から ⊥ のセマンティクスを導入しました。素晴らしい!


  1. 単純型付けされたラムダ計算とそれに近いもので固定小数点コンビネータを定義することは不可能であるため、基本的な固定小数点演算 (つまり、言語に組み込まれている演算) が必要です。( fixHaskell の Prelude での in の定義はこれと矛盾しません。再帰的に定義されていますが、再帰を実装するには固定小数点演算子が必要です。)

  2. これまでに見たことがない場合は、ラムダ計算の固定小数点再帰について読んでください。ラムダ計算に関するテキストが最適ですが (オンラインで無料のテキストがいくつかあります)、Google で調べてみるとよいでしょう。基本的な考え方は、再帰呼び出しを抽象化することで再帰定義を非再帰定義に変換し、固定小数点コンビネータを使用して関数 (ラムダ抽象化) をそれ自体に渡すことができるというものです。適切に定義された再帰的定義の基本ケースは、関数の不動点に対応するため、関数は実行され、不動点に達するまで何度も何度も自分自身を呼び出し、その時点で関数はその結果を返します。かなりきちんとしていますよね?

于 2013-04-10T01:42:36.163 に答える