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セクションを使うべきである。

参考:

テストで使うモジュールは全てexposeする

上記のようにlibraryセクションを設けてtest-suiteでそれを参照する場合、テストコードから参照できるのはlibraryセクションのexposed-moduleに書いたモジュールのみである。しかし(あまりよいことではないかもしれないが)、ユーザーに見せないプライベートな関数をテストしたり、テスト中で内部ユーティリティを活用したりしたいことはしばしばある。

そのような、「テストでは使うがユーザーには見せない」モジュールをうまいこと.cabalで指定する方法は今のところないらしい。そういったものも全てexposeする必要がある。exposeしてはいるがユーザー向けではないモジュールには名前に"Internal"を含めたりするのが慣習となっている。

参考:

doctestとhspecでテストを記述する

参考:

cabal initやhiでひな形を生成する

cabal initコマンドを使うと、パッケージのひな形を作成することができる。しかしcabal initは今のところtest-suiteセクションやテストのエントリポイントを自動生成しないため、毎回手で{-# OPTIONS_GHC -F -pgmF hspec-discover #-}と書くことになって精神衛生上よろしくない。

そこでひな形の生成にはhiというコマンドを使うとよいようだ。このコマンドはデフォルトでHspecのエントリポイントを生成する。また、ひな形の実体はgitレポジトリであるため、カスタマイズしたい場合はgithub上でforkしていじればOK。

参考: