Mac OS XのためのHaskell開発環境

はじめに

2012年ごろにとてもHaskellが流行り、たくさんの入門記事が書かれたものの、最近は関数型言語の物珍しさもあまりなくなり、むしろScalaやらC++11やらPythonの形に関数型の手法が定着しつつあるように感じます。

そんな中で出されたO'REILLY本「Haskellによる並列・並行プログラミング」を読み始めたわけですが、サンプルを動かそうとすると、これまでcabal installでホイホイしてきたせいで多くのパッケージの依存関係が壊れていてイライラする。

というわけでHaskellの恐らく今最もスタンダードな環境構築を一からやり直したので、知っておいた方がいい情報と合わせてメモしてみました。 OSはMac OS X Mavericks (10.9.4)です。

GHC・Cabalのインストール

Haskellコンパイラの定番GHCとパッケージ管理ツールCabalのインストールです。Mac OSなので素直にHomebrewでインストールしました。Linux環境でもapptitudeやyumで簡単にインストールできるはず。

$ brew install ghc cabal-install

結構時間がかかるかと思いますが、特にエラーなくインストール出来ました。 なにか怒られてもエラーを読んだりbrew doctorしてみたりすればすぐに出来るかと思います。

ちなみにインストールできたバージョンは + GHC version 7.8.3 + Cabal library 1.20.0.2 + cabal-install 1.20.0.3 でした。

また、インストールしたcabalコマンドを使うために.bash_profileなどお使いのシェルの起動時スクリプト$HOME/.cabal/bin環境変数PATHに追加しておくと楽でしょう。

GHCの使い方

GHCghcコマンドでソースコードコンパイルが出来る他、ghciコマンドで対話的な実行環境として実行できます。 主にghciコマンドは後述するcabal repl越しに関数の動き方の確認などに使用することとなるでしょう。

また、ghcコマンドにはGCCと同じように多彩なオプションが用意されています。 詳細はGHCのマニュアルを見ればわかりますが、以下に便利なオプションをいくつか書いておきます。

-o

$ ghc -o hoge Hoge.hs

基本ですが、一応。出力する実行ファイルの名前を指定します。 指定しない場合の出力ファイル名はmain関数を含むソースファイルのサフィックスを除いたものとなります。

-On

最適化オプションです。0~2の3段階があり、0は最適化なし、2は可能な限り最適化。指定しない場合は1となります。

-S

$ ghc -S Hoge.hs

...お楽しみオプションです。 ソースコードコンパイルアセンブルする前の状態(=アセンブリファイルを生成した状態)で止めます。 これによってGHCがどんなアセンブリを生成しているのか知ることができますが、ちょっとしたコードでもかなりの行数となるため、アセンブリコードからプログラムの性能を予測する、というのは現実的ではないかと思います。

ちなみに、GCCと同じように-cオプションでリンク前までコンパイルすることもできますが、GHCでは渡されたソースコードにmain関数が含まれていなかった場合は自動的にオブジェクトの生成まででストップするため、断片コードのコンパイル時に明示的に-cを付ける必要はありません。

cabalの使い方

Cabalを使うとRubyのBundlerのようにパッケージを管理することができます。 以下によく使用するコマンドを列挙しておきます。 なお、各コマンドのさらなる詳細は

$ cabal <コマンド名> --help

とするとみることができます。

init

$ cabal init

とすると対話的に自分の作成するプロジェクトのための.cabalファイルを作成することができます。

configure, build

$ cabal configure
$ cabal build

とするとカレントディレクトリのプロジェクトを.cabalファイルに基づいてビルドすることができます。 Makefileよりも最適化された形があるのはとても嬉しいですね。

update

$ cabal update

とすると最新のパッケージリストを取得できます。パッケージのインストールを行う前に実行します。

list

$ cabal list <文字列>

とするとbrew searchのように<文字列>にマッチするcabalでインストール可能なパッケージの一覧が取得できます。

info

$ cabal info <パッケージ名>

とするとbrew infoのように<パッケージ名>で指定したパッケージの詳細を表示します。

sandbox

$ cabal sandbox init

とするとbundle install--pathオプションのようにカレントディレクトリ以下でパッケージを個別に管理します(かつては同様の目的でcabal-devパッケージが使用されていました)。

sandboxを指定せずにcabal installをしてしまうと、プロジェクトごとに使用するパッケージのバージョンを管理できなくなるため、ひどいことになります。

パッケージのインストール前には必ずプロジェクト用のディレクトリを作成し、cabal sandbox initを叩くようにしましょう。

install

$ cabal install <パッケージ名>

とすると<パッケージ名>で指定したパッケージをインストールします。 前述のsandboxを使用していると、sandboxで指定されたディレクトリ(デフォルトでは./.cabal-sandbox)以下にパッケージがインストールされます。

-jnなどとすると-jnnで指定した数のジョブを同時に実行してくれるため、コアをフルに使ってインストールすることができます。

exec

$ cabal exec <コマンド名> -- <オプション>

とすると<コマンド名>で指定したsandbox内にインストールしたパッケージの実行ファイル(デフォルトでは./cabal-sandbox/bin以下にあるもの)を<オプション>付きで実行できます。

これもRubyのBundlerと似た機能ですね。

repl

$ cabal repl

とすると、カレントディレクトリのsandboxにインストールしたパッケージと.cabalファイルで指定されているmain関数のあるファイルをロードしたghciを起動することができます。

これはパッケージで提供されている関数などの挙動を確認する上で一番手っ取り早く、便利な方法になります。

ghc-pkgの使い方

ghc-pkgコマンドでインストール済みのパッケージに対する操作を行うことができます。 こちらも以下によく使うものを列挙しておきます。

list

$ ghc-pkg list

とすると、グローバルスコープのインストール済みパッケージを一覧できます。 この時、ghcのインストール場所のpackage.conf.d$HOME/.cabal以下のpackage.conf.dの2つに分かれてパッケージリストが表示されますが、前者がシステム用のパッケージ、後者がユーザのインストールしたパッケージのようです。

なお、Cabalを用いて

$ cabal exec ghc-pkg list

とするとsandboxにインストールしたパッケージも一覧することができます。

check

$ ghc-pkg check

とすると、依存関係の壊れたパッケージを一覧することができます。

field

$ ghc-pkg field <パッケージ名> <フィールド名>

とすると、<パッケージ名>に指定したパッケージの.confファイルの<フィールド名>に指定したフィールドの値を表示できます。

これを用いて

$ ghc-pkg field <パッケージ名> exposed-modules

とすれば、指定したパッケージで提供されるモジュールの一覧を表示できます。

unregister

$ ghc-pkg unregister <パッケージ名>

とすると、指定したパッケージをアンインストールすることができます。

おわりに

これらを知っておくだけで、かなりHaskellでの開発が楽しくなるかと思います。

というかたのしい。

参考サイト

Haskellのパッケージ管理について調べてみた - りんごがでている

2013年8月現在のHaskell開発環境 - maoeのブログ