7.1. GHCを使う

7.1.1. 始めよう: プログラムをコンパイルする

この章では,400を超えるフラグを含むGHCのコマンドライン構文の完全なリファレンスを示します. GHCは大きく複雑なシステムで,大量の詳細がありますのですので,どう始めてよいのかが判りにくでしょう. これを踏まえて,この節ではHaskellプログラムをコンパイルするためのGHCの基本的な使い方をざっと紹介します. これを読んでから,以降の節での完全な構文の解説に飛び込むのがいいでしょう.

Hello World プログラムを作って,これをコンパイルして,走らせてみましょう. まず,以下のHaskellコードを含む hello.hs を作成しましょう.

main = putStrLn “Hello, World!”

このプログラムをコンパイルするには以下のようにGHCを使います.

$ ghc hello.hs

(ここで $ はシェルのプロンプトですので,タイプする必要はありません.) GHCはソースファイル hello.hs をコンパイルして,オブジェクトファイル hello.o と インターフェイス hello.hi を生成してから,オブジェクトをGHC付属のライブラリとリンクして, Unix/Linux/Mac では hello という実行可能ファイルを Windowsでは hello.exe という実行ファイルを生成します.

デフォルトではGHCは自身の動作について寡黙で,表示するのはエラーメッセージだけです. 裏で何が行われているか詳細をみたいときには,コマンドラインに -v を追加すれば良いでしょう.

コンパイルができたら,以下のようにすればプログラムを実行できます.

$ ./hello
Hello World!

プログラムが複数のモジュールから構成されている場合でも,単に Main モジュールのファイル名を指定するだけですみます. GHCは Main モジュールの import 宣言を見て,プログラムを構成するその他のモジュールを見つけ,そのソースファイルを探します. したがって Main モジュールを除くモジュールのソースファイルはモジュール名を反映していなければなりません (ドットはディレクトリ区切り子に変換します). たとえば Data.Person モジュールは,Unix/Linux/Macでは Data/Person.hs というファイルに, Windowsでは Data\Person.hs というファイルに置くことになります.

7.1.2. オプションの概要

GHCの振る舞いはオプションによって制御します. 歴史的理由からオプションのことをコマンドラインフラグとかコマンドライン引数ともいいます. オプションの指定方法は3つあります.

7.1.2.1. コマンドライン引数

GHCを起動する構文は以下の形式になります.

ghc [argument...]

コマンドライン引数はオプションもしくはファイル名です.

コマンドラインオプションは - で始まります. これをひとまとめにすることは**できません**. -vO-v -O とは違うものであるということです. オプションをファイル名より前で指定する必要はありません. たとえば ghc *.o -o foo のようにできます. すべてのオプションを処理してから,それらをすべてのファイルに適用します. そのため ghc -c -O1 Foo.hs -O2 Bar.hs とやって Foo.hsBar.hs に異なる最適化水準を適用することはできません.

Note

コマンドラインオプションは 順序依存 であることに注意してください.引数は左から右へ評価されます. このことによって,フラグの連動がある場合おかしな効果があらわれことがあります. たとえば -fno-specialise-O1 (このフラグにより -fspecialise が有効になる) とを考えてみましょう. つぎの2つのコマンドラインは全く別ものです.

-fno-specialise -O1

-fno-specialise-O1 が上書きして -fspecialise が有効になります.

-O1 -fno-specialise

-O1 に連動する -fspecialise-fno-specialise で上書きされてしまうので有効になりません.

7.1.2.2. ソースファイル中のコマンドラインオプション

ソースファイルとコマンドラインを強く結びつけた方が便利なことがあります. たとえば,意図して名前のシャドーイングをおこなっているHaskellソースがあれば, そのファイルについては -Wno-name-shadowing オプション付きでコンパイルすべきです. Makefile をつかって,ファイルごとのオプション一覧を管理する代りに, OPTIONS_GHC pragma を使ってソースファイルに直接書いておけます.

{-# OPTIONS_GHC -Wno-name-shadowing #-}
module X where
...

OPTIONS_GHCファイルヘッダプラグマ (OPTIONS_GHC pragma 参照)です.

OPTIONS_GHC プラグマ中で使えるのは 動的 フラグだけです(静的オプション,動的オプション,モード指定オプション 参照).

コマンドシェルからこのソースオプションを取得するわけではなく, コンパイラが内部的に保持しているコマンドライン引数配列に含めるだけであることに注意してください. そのため OPTIONS_GHC の中でワイルドカードを使おうとすると残念なことになります.

Note

OPTIONS_GHC の内容はコマンドラインオプションの後に連結するので, コマンドラインで与えられたオプションがソースファイルオプションで上書きされます.

Makefile の内容をすべてソースファイルに移すのは推奨しませんが, 場合によっては OPTIONS_GHC プラグマを使うのが正しいやり方になります. (-keep-hc-file を使っていて,モジュールに OPTION フラグがあるなら, 生成した .hc ファイルには OPTIONS_GHC が置かれます.)

7.1.2.3. GHCiからオプションを設定する

GHCi内から :set コマンドを使ってオプションを変更することもできます.

7.1.3. 静的オプション,動的オプション,モード指定オプション

GHCのコマンドラインオプションは,静的オプション,動的オプション,モード指定オプションのいずれかに分類されます.

--make-E はモード指定フラグです.モード指定フラグはコマンドラインで1つだけ指定できます. 利用可能なモードの一覧は 実行モード にあります.

モード指定フラグではない大部分のフラグは動的フラグに分類されます. 動的フラグは,コマンドライン,ソースファイルの OPTIONS_GHC プラグマ, GHCi内の :set コマンドのいずれの方法でも設定できます.

残りのすこしばかりのフラグが静的フラグに分類されます.これらのフラグはコマンドラインでのみ使用可能で,1回のGHC/GHCiの実行を通し有効です.

フラグの参照表は(Flag reference)にはそれぞれどのフラグがどれに分類されているかが判るようになっています.

静的でありながら,GHCiの :set コマンドで設定できるフラグも少しながらあります. これは参照表では「static/:set」と表記されています.

7.1.4. 重要な意味のあるファイル接尾辞

「意味のある」接尾辞 (たとえば .lhs あるいは .o)の付いたファイルは,それにしたがって「適切な」方法で処理されます.

.hs
Haskellモジュール.
.lhs

「文芸的Haskell」モジュール.

.hspp
プリプロセッサが生成したファイル.
.hi
Haskellインターフェイスファイル,コンパイラが生成したものであることが多い.
.hc
Haskellコンパイラが生成した中間のCファイル.
.c
Haskellコンパイラが生成したCファイル以外のCファイル.
.ll
中間言語llvmのソースファイル.通常コンパイラが生成する.
.bc
中間言語llvmのビットコードファイル.通常コンパイラが生成する.
.s
アセンブリ言語のソースファイル.通常コンパイラが生成する.
.o
アセンブラが生成するオブジェクトファイル.

これ以外の接尾辞が付く(あるいは接尾辞の付かない)ファイルは直接リンカに渡されます.

7.1.5. 実行モード

GHCの振る舞いはまずモード指定フラグで制御します. モード指定フラグは1つしか与えられませんが,コマンドラインにおいて最初のオプションである必要はありません. 以下は指定例です.

$ ghc Main.hs --make -o my-application

モード指定フラグがない場合,コマンドラインでHaskellのソースファイルが指定されていれば --make モード(ghc –make を使う)になり,そうでなければ,コマンドライン中で指定さたオブジェクトをリンクして実行可能ファイルを生成します.

以下のモード指定フラグが利用可能です.

--interactive

対話モード. ghci としても使えます. 対話モードの詳しい説明は GHCiを使う を参照してください.

--make

このモードではGHCは複数のモジュールからなるHaskellプログラムを依存性を解析しながら自動的にビルドします. 単純なHaskellプログラムなら,これは make を使うよりずっと簡単でしかも速くビルドできます. makeモードについては ghc –make を使う で解説しています.

コマンドラインでHaskellのソースコードを指定した場合は,このモードがデフォルトになります. その場合 --make オプションは省略できます.

-e ⟨expr⟩

式評価モード.対話モードとほぼ同じですが, 評価する式(⟨expr⟩)は1つだけで,コマンドラインで与えます. 詳細については 式評価モード を参照してください.

-E
-C
-S
-c

これは伝統的なバッチ処理コンパイラモードです.GHCは1度に1つのソースファイルをコンパイルするか, オブジェクトファイルをリンクして1つの実行可能ファイルを生成します. 一括コンパイラモード を参照してください.

-M

依存性生成モード.このモードでは,GHCを使って Makefile ファイルで使うのに適した依存性情報を生成できます. Dependency generation を参照してください.

--frontend ⟨module⟩

指定したフロントエンドプラグインを使ってGHCを走らせます.詳細は Frontend plugins を参照してください.

--mk-dll

DLL作成モード(Windows のみ). Creating a DLL を参照してください.

--help
-?

GHC は使い方に関する長いメッセージを標準出力に吐いて,終了します.

--show-iface ⟨file⟩

⟨file⟩ 中のインターフェイスを読んで,それをテキストとして stdout にダンプします. たとえば ghc --show-iface M.hi のように使います.

--supported-extensions
--supported-languages

サポートしている言語拡張を表示します.

--show-options

サポートしているコマンドラインオプションを表示します.シェルでの自動補完のために使えます.

--info

コンパイラに関する情報を表示します.

--version
-V

GHCのバージョン番号を含む1行の文字列を表示します.

--numeric-version

GHCのバージョンを数値でのみ表示します.

--print-libdir

GHCライブラリディレクトリのパスを表示します. このパスはGHCのライブラリ,インターフェイス,インクルードファイルが置かれているディレクトリツリーの最上位です (通常 Unix では /usr/local/lib/ghc-8.0.2 のような場所です). これはパッケージの設定ファイル(Packages 参照)における $libdir の値です.

7.1.5.1. ghc --make を使う

このモードではGHCは複数のモジュールからなるHaskellプログラムをビルドします. このとき,GHCは1つ以上のルートモジュール(通常は Main のみ)から依存性を追跡します. たとえば Main モジュールが Main.hs というファイルに置かれているとき, 次のようにすればこのプログラムをコンパイルリンクできます.

ghc --make Main.hs

実際には,コマンドライン中に1つでもHaskellソースファイルがあり,他のモードが指定されていなければ,GHCは自動的にmakeモードになります. したがって,これ例では以下のようにタイプするだけでよいのです.

ghc Main.hs

ソースファイル名やモジュール名はいくつでも指定できます. GHCは,指定されたこれらの初期ファイルからインポートを追いかけて,プログラムに含まれるすべてのモジュールを見つけだします. 次に,最新ではないモジュールの再コンパイルを試み,最後に Main モジュールがあれば,プログラムをリンクして実行可能形式にします.

伝統的な Makefile に対して ghc --make を使う利点は,以下のようなことです.

  • コンパイルごとにGHCを再起動する必要がないので,それぞれのコンパイル間で情報をキャッシュできます. 複数のモジュールからなるプログラムを ghc --make でコンパイルする方が, 個々のソースファイルを1つずつコンパイルするより2倍も速くなることがあります.

  • Makefile を書かなくて済みます.

  • GHCは起動されるごとに依存関係を再計算するので, ソースとの整合性が失われることはありません.

  • -j フラグを使えば,モジュールを並列にコンパイルできます. -j⟨N⟩ と指定すれば ⟨N⟩ 個のジョブが並列に走ります.N を省略した場合は,デフォルトではプロセッサの数になります.

この章でこれ以降に解説するコマンドラインオプションはどれも --make オプションと共用できます. ただし,コマンドラインから与えれらたオプションはコンパイルするすべてのソースファイルに適用されるので, 個別のファイルにだけ適用したいオプションについては OPTIONS_GHC プラグマを使う必要があります(ソースファイル中のコマンドラインオプション 参照).

プログラムを追加のオブジェクト(たとえば,補助的なCのコード)とリンクする必要があるなら, そのオブジェクトファイルをコマンド行で与えれば,GHCは実行可能ファイルをリンクするときに指定されたオブジェクトを含めます.

既存の make スクリプトとの後方互換性確保のため -c と組み合わせて使うと,リンクのフェーズは省略します (--make -no-link を指定したのと同じ).

GHC はソースファイルがあるときにしか依存性を追跡できないので, ソースファイルのないモジュールがプログラムに含まれていると, たとえそのモジュールのオブジェクトファイルとインターフェイスファイルがあっても, GHCは文句をいうことに注意してください. ただし,パッケージモジュールの場合は例外で,このときはソースファイルはあってもなくてもかまいません.

プログラムのソースファイルはすべて同一のディレクトリにある必要はありません. -i オプションを使って探索パスを追加できます(The search path 参照).

-j [N]

可能であればコンパイルを並列で行います.GHC はコンパイル中に ⟨N⟩ 個までのスレッドを使います. N の指定が省略されたばあいは,デフォルト値はプロセッサ数です. モジュールのコンパイルは,それが依存しているモジュールのコンパイルが済んでから開始するということに注意してください.

7.1.5.2. 式評価モード

このモードは対話モードとほぼ同じですが,評価する式は1つだけで,コマンドラインから -e オプションの引数として指定します.

ghc -e expr

コマンドラインで Haskell のソースファイルを指定することもできます. 指定したファイルは対話モードと全く同じようにロードします. 指定した式はロードしたモジュールの文脈で評価します.

たとえば Main というモジュールを含む Haskell プログラムをロードして走らせるには,次のようにすればよいでしょう.

ghc -e Main.main Main.hs

また,このモードを使えば,単に式を Prelude の文脈で評価できます.

$ ghc -e "interact (unlines.map reverse.lines)"
hello
olleh

7.1.5.3. 一括コンパイラモード

一括処理モード で GHC はコマンドラインで指定した1つ以上のソースファイルをコンパイルします.

複数ある段階のどこから始めるかは,それぞれのファイルの接尾辞によって決まります. どこで終るかはフラグで指定します. 特にフラグによる指定がなければ,リンクまでの全ての段階を実行します. 以下の表にまとめておきます.

コンパイルシステムの段階 「ここから開始」の接尾辞 「ここで終了」のフラグ 出力ファイルの接尾辞
文芸形式プリプロセッサ .lhs   .hs
C プリプロセッサ(省略可) .hs (-cpp を使う) -E .hspp
Haskell コンパイラ .hs -C, -S .hc, .s
C コンパイラ(省略可) .hc or .c -S .s
アセンブラ .s -c .o
リンカ ⟨other⟩   a.out

そういうわけで,多くの場合,次のように起動します.

ghc -c Foo.hs

これで,Haskellのソースファイルが Foo.hs をコンパイルすると,オブジェクトファイル Foo.o が生成されます.

Note

Haskellのコンパイラが実際に出力するのが何かはバックエンドのコード生成器が何であるかによります. 詳細については GHC Backends を参照してください.

Note

C のプリプロセッサは省略可能で -cpp フラグを指定すれば有効になります. 詳細については Options affecting the C pre-processor を参照してください.

Note

-E オプションを指定するとコンパイラのプリプロセス段階だけが実行され結果がファイルに出力されます.

Note

-C オプションはGHCが未登録モードでビルドされているときにだけ利用可能です. 詳細については Unregisterised compilation を参照してください.

7.1.5.3.1. ファイルに対するデフォルトの振る舞いを上書きする

上述のように,GHCがファイルを処理する方法はファイルの接頭辞で決まります. この振る舞いは -x オプションで変更できます.

-x ⟨suffix⟩

コマンドラインにおいて,このオプションに続くすべてのファイルに指定した接尾辞 ⟨suffix⟩ が付いているものとして扱います. たとえば M.my-hs というファイルにある Haskell モジュールをコンパイルするには ghc -c -x hs M.my-hs とします.

7.1.6. 饒舌性に関するオプション

実行モード にある --help--version--numeric-version--print-libdir の各モードについても参照してください.

-v

-v オプションにより GHC は 饒舌 になります. GHCはバージョン番号を報告し,コンパイルシステムの各段階ごとに,どのように起動したかを(標準エラー出力に)表示します. さらに,ほととんどの段階に -v フラグを渡し,それぞれがバージョン番号(やそれ以外の情報)を報告します.

バグ報告するときは,お願いですから -v を使ってください. 正しいことが正しい順序でおこなわれていることを先ず確認したいからです.

-v ⟨n⟩

より細かく饒舌性を制御するために -v は省略可能は数値引数を与えられるようになっています. -v を単独で指定するのは -v3 を指定するのと同じです.その他のレベルには以下のものがあります.

-v0
本質的ではない全てのメッセージを無効にします(これがデフォルト).
-v1
最小限の饒舌性.コンパイルごとに1行表示します(--make あるいは --interactive が指定されたときはこれがデフォルト).
-v2
各コンパイル段階を実行するときに,その段階の名前が表示されます(-dshow-passes を指定したのと同じ).
-v3
各コンパイル段階について完全なコマンドライン(あれば)を表示します.それ以外は -v2 と同じです.
-v4
各コンパイル段階が終った後に (プリプロセッサの結果およびC/アセンブリファイルを除く) その段階での中間形式でプログラムを表示します.
-fprint-potential-instances

GHC はクラスのインスタンスを見つけられなかったら,判っているインスタンスのうちいくつかを並べて表示します. このフラグが指定されているときには,判っているインスタンスを すべて 表示します.

以下のフラグはGHCのエラーメッセージとGHCiとにおける型情報の表示方法を制御するものです.

-fprint-unicode-syntax

このフラグが有効になっていれば,GHC は型シグネチャを言語拡張 -XUnicodeSyntax 由来のユニコード記号を使って表示します. たとえば,以下のような表示になります.

ghci> :set -fprint-unicode-syntax
ghci> :t (>>)
(>>) :: ∀ (m :: * → *) a b. Monad m ⇒ m a → m b → m b
-fprint-explicit-foralls

-fprint-explicit-foralls を指定すると GHC は型のトップレベルに,通常は表示されない forall 量化子を表示します. GHCi では,たとえば,以下のようになります.

ghci> let f x = x
ghci> :t f
f :: a -> a
ghci> :set -fprint-explicit-foralls
ghci> :t f
f :: forall a. a -> a

ただし,このフラグの設定いかんにかかわらず,以下の場合には量化子が表示されます.

  • 入れ子になった forall

    ghci> :t GHC.ST.runST
    GHC.ST.runST :: (forall s. GHC.ST.ST s a) -> a
    
  • 量化子付きの型変数のどれかがカインド変数で言及されているカインドをもつ

    ghci> :i Data.Type.Equality.sym
    Data.Type.Equality.sym ::
      forall (k :: BOX) (a :: k) (b :: k).
      (a Data.Type.Equality.:~: b) -> b Data.Type.Equality.:~: a
            -- Defined in Data.Type.Equality
    
-fprint-explicit-kinds

-fprint-explicit-kinds を指定すると,通常は表示されないカインドが型に表示されます. カインド多相を使っているときには重要な機能です.

ghci> :set -XPolyKinds
ghci> data T a = MkT
ghci> :t MkT
MkT :: forall (k :: BOX) (a :: k). T a
ghci> :set -fprint-explicit-foralls
ghci> :t MkT
MkT :: forall (k :: BOX) (a :: k). T k a
-fprint-explicit-runtime-reps

-fprint-explicit-runtime-reps が有効になっていると, GHC は実行時表現多相型について RuntimeRep 型変数を表示します. このフラグが有効になっていなければデフォルトでは PtrRepLifted になります. 以下はその表示例です.

ghci> :t ($)
($) :: (a -> b) -> a -> b
ghci> :set -fprint-explicit-runtime-reps
ghci> :t ($)
($)
  :: forall (r :: GHC.Types.RuntimeRep) a (b :: TYPE r).
     (a -> b) -> a -> b
-fprint-explicit-coercions

-fprint-explicit-coercions を指定すると GHC は型の変換を表示します. 異なるカインドの型間の相等性を証明しようとすると,GHC は型レベルの変換を使います. ユーザがこれ見なければならなくなるのは稀です.あくまでもコンパイラ内部のできごとだからです.

-fprint-equality-relations

-fprint-equality-relations を使って GHC に表示の際に相等性の関係を識別するよう指示できます. たとえば ~ 均質な持ち上げ(2つの引数は同じカインドをもつ)相等性関係であり, ~~ は異質な持ち上げ(2つの引数の型が異なる)相等性関係であり, ~# は異質な持ち上げていないGHC内部のソルバで使われる相等性関係です. 一般にユーザはこの微妙な部分について気を配る必要があるべきではなく, ~ が ユーザが欲っしているものでしょう. -fprint-equality-relations が指定されていなければ,GHCはすべて ~ として表示します. Equality constraints も参照してください.

-fprint-expanded-synonyms

これが有効になっていれば,GHC は型エラーメッセージで型シノニムを展開した型も表示します. たとえば,以下のような型シノニムがあったとしましょう.

type Foo = Int
type Bar = Bool
type MyBarST s = ST s Bar

以下のような型エラーメッセージ

Couldn't match type 'Int' with 'Bool'
Expected type: ST s Foo
  Actual type: MyBarST s

が以下のような型エラーメッセージになります.

Couldn't match type 'Int' with 'Bool'
Expected type: ST s Foo
  Actual type: MyBarST s
Type synonyms expanded:
Expected type: ST s Int
  Actual type: ST s Bool
-fprint-typechecker-elaboration

これが有効であれば GHC は警告メッセージで型検査器よりの追加の情報を表示します. たとえば,

main :: IO ()
main = do
  return $ let a = "hello" in a
  return ()

であるとします.以下の警告メッセージは

A do-notation statement discarded a result of type ‘[Char]’
Suppress this warning by saying
  ‘_ <- ($) return let a = "hello" in a’
or by using the flag -fno-warn-unused-do-bind

は以下のように表示されるようになります.

A do-notation statement discarded a result of type ‘[Char]’
Suppress this warning by saying
  ‘_ <- ($)
          return
          let
            AbsBinds [] []
              {Exports: [a <= a
                           <>]
               Exported types: a :: [Char]
                               [LclId, Str=DmdType]
               Binds: a = "hello"}
          in a’
or by using the flag -fno-warn-unused-do-bind
-ferror-spans

これを有効にすると,GHC はエラーメッセージに関連する構文上の実体のソースコード上の範囲を表示します. 通常 GHC は構文上の実体のソースコードの開始位置だけを表示します.

たとえば,

test.hs:3:6: parse error on input `where'

という表示だったものが,

test296.hs:3:6-10: parse error on input `where'

のような表示になります.また,範囲は複数行にまたがることもあるので,その場合は

test.hs:(5,4)-(6,7):
    Conflicting definitions for `a'
    Bound at: test.hs:5:4
              test.hs:6:7
    In the binding group for: a, b, a

のようになります.行番号は1から数えますが,カラム番号は0から数えることに注意してください. このような数えかたになっているのは,既存のよくある慣習(たとえば Emacs)にしたがったからです.

-H ⟨size⟩

ヒープの最小サイズを ⟨size⟩ に設定します.このオプションは +RTS -Hsize と同じです. RTS options to control the garbage collector を参照してください.

-Rghc-timing

GHC の実行に要した時間について統計情報を1行にまとめて表示します. このオプションは +RTS -tstderr と同じです. RTS options to control the garbage collector を参照してください.

7.1.7. プラットフォーム固有のオプション

特定のターゲットプラットフォームについてのみ意味のあるフラグがいくつかあります.

-msse2

(x86 のみ.GHC 7.0.1 で追加) native code generator を使う場合, 浮動小数点演算を実装するのに SSE2 のレジスタと命令セットを使います. これを指定すれば大幅に浮動小数点演算が改善されますが,コンパイルして得たコードは SSE2 をサポートしているプロセッサ(Intel の Pentium 4 以降と AMD Athlon 64 以降)上でないと動きません. プロセッサが SSE2 をサポートしていれば LLVM backend は SSE2 を使いますが, こちらは自動で認識しますので,フラグでの指定は不要です.

x86-64 のプラットフォームでは SSE2 は無条件で使われます.

-msse4.2

(x86 のみ.GHC 7.4.1 で追加). native code generator を使う場合, いくつかの浮動小数点演算とビット演算を実装するのに SSE4.2 命令セットを使います. コンパイルして得たコードは SSE4.2 をサポートしているプロセッサ(Intel の Core i7 以降)上でないと動きません. プロセッサが SSE4.2 をサポートしていれば LLVM backend は自動的にそれを認識しますので, して使うようになりますので,フラグ指定は不要です.