これからのHaskellプロジェクトではcabalではなくpackage.yaml(hpack)を使いましょう

sol/hpack: hpack: An alternative format for Haskell packages

hpackとは

hpackとは,cabalファイルを生成してくれるツールです.

package.yamlファイルからcabalファイルを生成します.

JavaScriptに対するAltJSのようなものです.

hpackは何が良いのか

yamlである

hpackのフォーマットであるpackage.yamlはyamlフォーマットです.

独自のフォーマットを採用しているcabalとは違い,様々なエディタが普通に対応しており,プログラムからも扱いやすくなっています.

ボイラープレートを自動生成してくれる

default-language: Haskell2010のような現代では当たり前の記述を自動生成してくれるため,わざわざ書かなくて済むようになります.

exposed-modulesを自動生成してくれる

cabalではexportするモジュールを全てlibraryexposed-modulesに書かなくてはいけませんでした.

hpackでは

library:
  source-dirs: src

のように書くだけで,src以下のモジュールを自動的にcabalに書いてくれます.

長い記述が不要になり,モジュールの名前が変わっても自動的に変更されるので,楽です.

other-modulesを自動生成してくれる

hspecなどを使うとtest-suiteother-modulesにたくさんSpecモジュールを書く必要がありますが,hpackを使うとこれも自動生成してくれます.楽です.

build-dependsの共通部分をまとめられる

cabalではlibrarytest-suiteなどのbuild-dependsに共通部分があっても,それらを全てコピペして並べなければいけませんでした.

面倒くさいですし,共通の依存が並んでいるとtest-suiteだけが要求するライブラリがわかりにくくなります.

hpackではトップレベルの場所にdependencies:を書いておくと,cabalファイルではlibraryexecutablestest-suiteもこの依存を継承するようになります.

後は以下のようにtests部分だけにtestだけが要求する依存をわかりやすく記述することが出来ます.

tests:
  test:
    main: Spec.hs
    source-dirs: test
    dependencies:
    - foo-application
    - hspec
    - yesod-test

githubのURLからhomepage,bug-reports,source-repositoryを自動生成してくれる

github: user/repo

のようにgithubのリポジトリを指定すると,自動的にcabalにhomepage,bug-reports,source-repositoryを記述してくれます.楽です.

変数が使える

cabalでは変数が使えなかったため,共通する記述もコピペするしか書く方法がありませんでしたが,hpackでは変数が使えるため,例えば共通するghcオプションなどを変数にまとめ,それぞれの場所で展開することが出来ます.

hpackを使うには

現在のstackはhpackにデフォルト対応しているため,package.yamlが存在するディレクトリでstack buildすれば自動的にcabalファイルを作成してビルドしてくれます.

cabalファイルは自動生成されるようになるため,cabalファイルは.gitignoreで除外しておくようにしましょう.

新規プロジェクトの場合

stack new foo simple-hpackのようにすると,hpackでプロジェクト設定が生成されます.

また,yesodもhpackを採用するようになったため,stack new foo yesod-postgresなどをしてもhpackが使われるようになります.

既存プロジェクトの移行

hpack-convert: Convert Cabal manifests into hpack’s package.yamlsを使えばcabalファイルから簡単にpackage.yamlを作成することが出来ます.

このツールは結構賢く,共通部分を自動的にまとめたpackage.yamlが生成されます.