Haskell/Yesod を Stackage でインストールする


Haskell の web アプリケーションフレームワークである Yesod を、Stackage レポジトリからインストールする方法についてのメモです。理解不足から間違いもあるかも知れませんので、ご指摘ください。 

# Hackage レポジトリについて

Hackage ([Hackage: Introduction](https://hackage.haskell.org/)) は、Haskell で書かれたライブラリのパッケージのレポジトリであり、Ruby で言うと RubyGems ([RubyGems.org | your community gem host](https://rubygems.org/)) のようなものです。それらのパッケージは、Cabal-Install ツールでパッケージをローカルへフェッチし、インストールすることができます。

# Cabal-Install について

Cabal-Install ([Cabal-Install - HaskellWiki](http://www.haskell.org/haskellwiki/Cabal-Install)) は、Haskell のパッケージをリモートからフェッチし、インストール・管理するためのツールです。Ruby で言えば Gem + Bundler のようなものです。システムワイドだけではなく、アプリごとに独立したサンドボックスにインストールすることもできます。

パッケージとしては、パッケージのビルドを担う「Cabal」と、フェッチ・インストール・管理を担う「Cabal-Install」とに分かれており、そのへんの関係については「[Cabal - HaskellWiki](http://www.haskell.org/haskellwiki/Cabal)」に記載があるのですが、ぶっちゃけ Homebrew や Ubuntu で「cabal-install」パッケージを入れれば勝手に Cabal も入りますので、あまり深く考えずに「cabal-install」を入れれば良いです。

なお、アップデートやアンインストールには対応していないようですので、Gem/Bundler 並を期待してはいけない模様。

# Stackage が有り難すぎる

Hackage 内のパッケージには、パッケージ間の依存関係やビルドのオプション等のメタ情報が記載されていて、本来であればそれに従って綺麗にビルド・インストールができるはずなのですが、なにぶんにも今までの全パッケージの全バージョンが格納されているため、依存関係や GHC のバージョンなどが鬼のように複雑なので、ネット上にある「こうすれば Yesod がインストールできた」手順の通りに実行しても、今時点のレポジトリの状態によっては、インストールが出来たり出来なかったりします。RPM で言えば distro バージョン無視で全パッケージを格納してしまった yum レポジトリみたいなものでしょうか。そりゃうまく行かないと思われます。

そのようなわけで Hackage が使いづらすぎるというか、使えないレベルになってしまったので、Stackage プロジェクト ([Stackage Server](http://www.stackage.org/)) が立ち上がりました。Hackage の中から、その時々で（スナップショットで）管理対象となっているパッケージのみを依存関係を満たして一つずつ抜き出し、格納しているレポジトリです。

FAQ にもありますが、「exclusive」レポジトリは、Stackage 管理パッケージのみを一つずつ格納したレポジトリであり、「inclusive」レポジトリは、Stackage 管理パッケージ一つずつに加えて、管理外のパッケージも含めたレポジトリです。

# ライブラリ環境の isolation は、Cabal の sandbox よりも hsenv で

共通の Cabal 設定（~/.cabal/config で設定する）ではレポジトリの URL を一つしか持てないため、同一開発環境上に複数のアプリケーションごとに必要とする GHC のバージョンや Stackage のスナップショットバージョンが異なると共存しづらくなってしまいます。

そこで、hsenv ([Hackage: hsenv: Virtual Haskell Environment builder](https://hackage.haskell.org/package/hsenv)) で Cabal 設定自体を切り替えるようにした方が良いと思います。同一の開発環境内に、異なるの Stackage スナップショットバージョンを用いるアプリケーションを共存させられるし、追々は、GHC のバージョンが異なるスナップショットどうしも共存できるので、sandbox だけで環境を切り分けるよりも良いでしょう。

# hsenv の導入

Homebrew でも Ubuntu でも、必要なアプリのパッケージは「cabal-install」です。

~~~~bash:-
$ brew install cabal-install
~~~~

~~~~bash:-
$ sudo aptitude install cabal-install
~~~~

最初に、hsenv を入れます。今日時点で hsenv は Stackage の管理外のようですので、Hackage か、Stackage の inclusive レポジトリからインストールします。

~~~~bash:-
$ cabal update
$ cabal install hsenv-0.4 -j2
~~~~

それでコケるようであれば、mtl のバージョンを指定します（なんで mtl-1.1.1.1 の方を取ってきてしまうのかなぁ…）。

~~~~bash:-
$ cabal install mtl-2.1.3.1 hsenv -j2
~~~~

hsenv 環境のディレクトリを作成し、Stakage のレポジトリを指定します。

~~~~bash:-
$ mkdir yesodtest
$ cd yesodtest
$ hsenv
$ sed -i -e 's@^remote-repo:.*@remote-repo: stackage-cb4b6c74f4566eb5ccaeb2c2784f2db795c5450e:http://www.stackage.org/stackage/cb4b6c74f4566eb5ccaeb2c2784f2db795c5450e@' .hsenv/cabal/config
~~~~

# Yesod の導入

Yesod のコマンドラインをインストールして Yesod アプリケーションを作成し、必要なライブラリをインストールします。

~~~~bash:-
$ source .hsenv/bin/activate
$ cabal update
$ cabal install alex happy yesod-bin -j2
$ PATH=$PATH:.hsenv/cabal/bin yesod init --bare # パス指定、要らないんじゃ？
$ cabal install -j2
$ PATH=$PATH:.hsenv/cabal/bin devel # ここも
$ deactivate_hsenv
$ 
~~~~