Closed6

Haskellでちょっとしたスクリプトを書く

だめぽだめぽ

Haskellで本格的に開発する際はcabalなりstackなりでプロジェクトを作るわけですが、ファイル一つで済むような(書き捨て)スクリプトをHaskellで書きたい場合があります。

依存関係のないスクリプトであれば、普通にファイルを作ってrunghc/runhaskellすれば良いでしょう。しかし、Haskellには標準ライブラリー(base)以外にも「準標準」と呼べる外部のライブラリーが多数あり(例:bytestring, text, vector)、それらに明示的に依存することはrunghcではできません。

そこで使えるのが、cabal scriptやstack scriptと呼ばれる機能です。歴史的にはstack scriptの方が古く(いつ?)、cabal scriptは2018年ごろに実装された比較的新しい機能です。

だめぽだめぽ

cabal script

cabal v2-run コマンドを使うと、ファイル中に {- cabal: 形式の特殊なコメントを含むHaskellコードをその場でビルドして実行することができます。

例:

#!/usr/bin/env cabal
{- cabal:
build-depends: base, bytestring ^>= 0.11.3.0
-}
import qualified Data.ByteString.Char8 as BS
main = BS.putStrLn (BS.pack "Hello world!")

実行例:

$ cabal v2-run hellocabal.hs
…略…
Hello world!
$ chmod +x hellocabal.hs
$ ./hellocabal.hs
…略…
Hello world!

{- cabal: はその行に単独で存在する必要があります。

shebangは、 cabal v2-run 経由で実行する場合は必要ありません。

だめぽだめぽ

stack script

例:

#!/usr/bin/env stack
-- stack script --resolver lts-18.28 --package bytestring --package vector
import qualified Data.ByteString.Char8 as BS
import qualified Data.Vector as V
main = do BS.putStrLn (BS.pack "Hello world!")
          print (V.sum (V.fromList [1..100]))

実行例:

$ stack hellostack.hs
Hello world!
5050
$ chmod +x hellostack.hs
$ ./hellostack.hs 
Hello world!
5050

stackへのオプションを指定する行はshebangを除いた最初の行(shebangがあれば2行目、shebangがなければ1行目)から始まる必要があります。{- -} 形式のコメントを使うことで複数行にわたって記述できます。

--package を全く指定しなかった場合は、import の内容から推測してくれます。

shebangは、stack 経由で実行する場合は必要ありません。

だめぽだめぽ

利用例

ちょっとしたスクリプトとして使う

例:https://github.com/minoki/icfpc2006/blob/master/extract-CBV.hs
bytestringとJuicyPixelsに依存するcabal script。

コードを貼るときに依存関係を明示するのに使う

例:Misleading GHC error when function is not in scope (#16491) · Issues · Glasgow Haskell Compiler / GHC · GitLab
GHCのバグ報告の再現コードが外部ライブラリーに依存する際にそれを明示するために使う。人間にとっても読める。

このスクラップは2022/11/17にクローズされました