cabalを使ってHaskellのプログラムを作り始める時のメモ
公開しようがしまいが、Haskellでプログラムを作る時はcabalを全面的に使うといろいろメンテしやすい。しかしその使い方(特に.cabalファイルの書き方)は自明ではないということで、いろいろ調べたのでメモ。
.cabalファイルには、とりあえずlibraryセクションは書いておく
executableセクションがあろうがなかろうが、自分で書いたモジュールのほぼ全てをlibraryセクションに突っ込んでおくのがよいようだ。executableセクションやtest-suiteセクションで自分の書いたモジュールを参照するためには、各セクションのbuild-dependsに自分自身のパッケージ名を書いておく。
なお、executableパッケージを作る場合、libraryセクションがなくてもtest-suiteのhs-source-dirsにexecutable用のコードを入れたディレクトリを指定すればテストを書くことができる。しかしこれには以下の欠点がある。
- executable用のコードはexecutableのビルド時とtest-suiteのビルド時の2回、コンパイルされてしまう。
- test-suiteのbuild-dependsにはテストコードと参照するexecutable用のコードの両方の依存パッケージを書く必要がある。
両方共DRY原則に激しく反するため、精神衛生上よろしくない。libraryセクションを使うべきである。
参考:
- haskell - How to reduce duplication in the build-depends fields of a .cabal file? - Stack Overflow http://stackoverflow.com/questions/10163604/how-to-reduce-duplication-in-the-build-depends-fields-of-a-cabal-file
- Haskellのexecutableなプログラムでテスト自動化 - Qiita http://qiita.com/arowM/items/1a56cc208e418829a097
テストで使うモジュールは全てexposeする
上記のようにlibraryセクションを設けてtest-suiteでそれを参照する場合、テストコードから参照できるのはlibraryセクションのexposed-moduleに書いたモジュールのみである。しかし(あまりよいことではないかもしれないが)、ユーザーに見せないプライベートな関数をテストしたり、テスト中で内部ユーティリティを活用したりしたいことはしばしばある。
そのような、「テストでは使うがユーザーには見せない」モジュールをうまいこと.cabalで指定する方法は今のところないらしい。そういったものも全てexposeする必要がある。exposeしてはいるがユーザー向けではないモジュールには名前に"Internal"を含めたりするのが慣習となっている。
参考:
- haskell - cabal test for not exposed modules - Stack Overflow http://stackoverflow.com/questions/25618244/cabal-test-for-not-exposed-modules
doctestとhspecでテストを記述する
参考:
cabal initやhiでひな形を生成する
cabal initコマンドを使うと、パッケージのひな形を作成することができる。しかしcabal initは今のところtest-suiteセクションやテストのエントリポイントを自動生成しないため、毎回手で{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
と書くことになって精神衛生上よろしくない。
そこでひな形の生成にはhiというコマンドを使うとよいようだ。このコマンドはデフォルトでHspecのエントリポイントを生成する。また、ひな形の実体はgitレポジトリであるため、カスタマイズしたい場合はgithub上でforkしていじればOK。
参考:
- Haskellプロジェクトのひな形生成ツールを作った http://fujimuradaisuke.com/haskell_advent_calendar_2013.html
- fujimura/hi https://github.com/fujimura/hi