Glasgow Haskell Compiler
Glasgow Haskell Compiler
Glasgow Haskell Compiler (グラスゴー・ハスケル・コンパイラ) またはThe Glorious Glasgow Haskell Compilation System (ザ・グロリアス・グラスゴー・ハスケル・コンピレーション・システム) は、関数型プログラミング言語 Haskellのオープンソースコンパイラである。一般的にGHCの略称で知られている。Haskellのコードの作成とテストのためのクロスプラットフォーム環境を提供し、効率的な実行ファイルを生成するための多数の言語拡張・ライブラリ・最適化に対応している。GHCは最も一般的に利用されているHaskellのコンパイラである。主要開発者はサイモン・ペイトン・ジョーンズとサイモン・マーロウである。
GHCの開発は、1989年にグラスゴー大学のKevin Hammondによって開始された。プロトタイプはレナート・オーガストソンによって書かれていた。この年の後半にパーサを除いた部分が、Cordelia HallとWill PartainとSimon Peyton JonesによってHaskellで完全に書き直された。最初のベータ版は1991年4月1日にリリースされ、その次のリリースでは、厳密なアナライザーとモナドなどのより良い言語拡張、変更可能な配列 (MArray)、ボックス化されていないデータ型、ソフトウェアトランザクショナルメモリやデータ並列性などの並列プログラミングモデル、プロファイラーが追加された。
Simon Peyton JonesとSimon Marlowは後に、ケンブリッジのマイクロソフトリサーチに移籍し、そこでGHCの開発を行っている。GHCの開発には300人以上が貢献している。2009年以降、サードパーティーのGHCへの貢献には、Industrial Haskell Group (IHG) によって資金提供が行われている。
GHC自体はHaskellによって書かれているが、プログラムの実行に必要なランタイムシステムは、C言語とC--によって書かれている。
字句解析・パーサ・型システムが組み込まれているGHCのフロントエンドは、型推論が完了するまで可能な限りソースコードに関する情報を保存し、ユーザーに明確なエラーメッセージを提供することを目標に設計されている。型検査が完了した後、Coreとして知られている非糖衣構文の型付きの中間言語に変換される。最近のCoreは一般化された代数的データ型に対応するように拡張され、System FCとして知られているSystem Fの拡張に基づいている。
型指向コンパイルの伝統では、GHCのコンパイラ最適化が実行される単純化 (ミドルエンド) の段階は、一連のCoreのコードのトランスコンパイルによって構成されている。この段階で行われる解析と変換は、需要解析 (正格性解析の一般化)、ユーザー定義の項書き換えの適用 (foldr/build森林破壊 (計算機科学)を実行するGHCの標準ライブラリに含まれる一連の規則を含む)、展開 (より伝統的なコンパイラでは「インライン展開」と呼ばれているもの)、ボックス化を解除できる関数の引数がどれであるかの解析、構築された製品の結果解析、多重定義された関数の部分評価、定数畳み込みやベータ簡約などのより簡単な局所変換である。
GHCのバックエンドは、中間言語 Spineless Tagless G-machine (STG) を介してCoreのコードをC--の内部表現に変換している。C--のコードは以下の3つの中のいずれかの方法によって変換される。
GCCでコンパイルするためのC言語のコードを出力。
機械語に直接変換 (従来のコード生成)。
LLVMでコンパイルするための中間言語 (LLVM IR) に変換。
いずれの方法でも最終的に得られた機械語はGHCのランタイムシステムとリンクされ、実行ファイルが生成される。
GHCはHaskell 98とHaskell 2010の両方の言語標準に対応している。また、言語標準に対する多くの言語拡張にも対応している。例えば、合成可能メモリトランザクションを可能にするソフトウェアトランザクショナルメモリ (STM) のライブラリである。
Haskellの言語標準には幾つかの拡張が提案されている。これらの言語拡張は言語仕様では記述されていない機能を提供するか、既存の構造を再定義している。これらの言語拡張は全てのHaskell処理系が対応しているわけではない。言語拡張を記述し、将来の言語仕様に含めるものを選択する継続的な努力が行われている。
GHCが対応している言語拡張は以下の通りである。
ボックス化されていない型と操作。これらはヒープへのポインタの間接参照や遅延評価の可能性を除外して、基礎となるハードウェアのプリミティブ型を表す。数多くのコードは、これらの型を使用することにより大幅な高速化が可能である。
値、パターン・バインディング、データ型領域の正格評価を指定する機能。
モジュール・パターン・リスト内包表記・演算子・レコード・タプルの操作により便利な構文。
矢印を使用して計算するための糖衣構文と再帰的に定義されたモナドの値。これらはどちらも言語標準のモナドのdo-notationを拡張している。
Template Haskellは、コンパイル時のメタプログラミングのためのシステムである。プログラマは抽象構文木の形でHaskellのコードを生成する式を書くことができる。これらの式はコンパイル時に型検査が行われる。生成されたコードはプログラマによって直接書かれたように見える。定義に反映するための能力と共に、更なる言語拡張のための強力なツールを提供する。
擬似引用を利用することで、ユーザーは式とパターンのための新しい具体的な構文を定義することができる。この機能は、Haskellで書かれたメタプログラムが、Haskell以外で書かれたコードを操作する場合に便利である。
ジェネリック型クラスは、操作する型の代数的構造だけで関数を指定する。
複数のコアを利用した式の並列評価。この機能では明示的にスレッドを指定する必要はない。プログラマが提供する注釈に基づいて、暗黙的に作業の分散が行われる。
インライン展開などの最適化を指示するコンパイラプラグマと、特定型のための特殊関数。
変更可能な項書き換え。プログラマはある1つの式を、等価なより効率的に評価された式に置き換える方法を記述するルールを提供することができる。この機能は、アプリケーションレベルのコード全体で、データ構造ライブラリの中心部を効率化するために利用されている。
表現力豊かな静的型付けは、Haskellの主な特徴の1つである。それ故に、言語拡張の作業の多くは型と型クラスに向けたものになっている。
GHCはSystem FCに基づいた拡張型システムに対応している。主な型システムの拡張は以下の通りである。
任意ランクと非可述的多相性。本質的には、多相関数またはデータ型コンストラクタは、引数の1つが多相であることを必要とする場合がある。
一般化代数的データ型。多相データ型の各コンストラクタは、結果の型に情報をエンコードすることができる。この型でパターンマッチを行う関数は、コンストラクタごとの型情報に基づいて、データに対してより具体的な操作を行うことができる。
存在型は、一部のデータとそのデータの操作を束ねて、基礎となるデータのデータ型を隠蔽して操作することができる。このような値は、オブジェクト指向プログラミングのオブジェクトと非常に似たものである。
値を含まないデータ型。この機能は型レベルのメタプログラミングでデータを表現するときに便利である。
型族は、型から型へのユーザー定義関数である。パラメータ多相は各型のインスタンス化に同じ構造を提供するが、型族はインスタンス間で異なる実装によりアドホック多相を提供する。ユースケースには、内容に応じたコンテナの最適化と、型レベルのメタプログラミングが含まれている。
動的スコープを持つ暗黙的な関数パラメータ。これは型クラスの制約と同様に、型で表現される。
型クラスに関する拡張は以下の通りである。
型クラスは複数の型によってパラメータ化することができる。従って、型クラスは型の組だけでなく、n-項関係を記述することができる。
関数従属性は、その部分の関係を型の数学的関数に制約する。つまり、ある型タイプの一方のパラメータが固定されると、もう一方のパラメータが完全に決定するように束縛が指定される。これは曖昧さがある状況で型推論ができる方法を案内する。
型クラスのインスタンスの許容できる形状に関するルールを大幅に緩めた。これが全て有効なとき、型クラスシステムはコンパイル時に論理プログラミング向けのチューリング完全な言語となる。
型族は型クラスに関連付けることができる。
確実な型クラスのインスタンスの自動生成は、幾つかの方法で拡張されている。ジェネリックプログラミングと一般再帰パターン向けの新たな型クラスに対応している。更に、新しい型が既存の型と同じであると宣言された場合、基の型に対して宣言された型クラスのインスタンスは、空の新しい型に昇格する可能性がある。
GHCはUnix系OS (Linux・FreeBSD・macOSなど) やWindowsなど多くのプラットフォームで動作し、パッケージ管理システムを利用してインストールすることもできる。また、x86やPowerPC、ARMなど多くのCPUで稼動するOS上に移植されている。