お布団宇宙ねこ

にゃーん

Stack を使って Haskell の Hello World をやってみる

以前 Stack を使って すごいH本 を学習したのですが、それっきり全く Haskell に触れていなかったのでリハビリがてら、 Stack を導入して Hello World を出力するまでの方法について書いておきます。

Stack のインストール

Mac の場合は Homebrew を使ってインストールできます。

brew install haskell-stack

プロジェクトの作成とビルド

公式の Quick Start Guide に書いてある通りにやりましょう。

Quick Start Guide — stack documentation

stack new my-project
cd my-project
stack setup
stack build

Hello World!

次は、プロジェクトの中身を少し修正しておなじみの Hello World を出力してみましょう。

app/Main.hs

module Main where

import Lib

main :: IO ()
main = someFunc

app/Main.hs がメインのパッケージです。

Hello World を出力するためには、この中の main 関数を修正すればよさそうですが、コードを見た限りだと mainsomeFunc という関数を指しているだけです。

someFunc の実体は Lib パッケージ内にあります。 import LibLib パッケージをインポートしていてその関数を使っているわけです。 インポートされているパッケージはデフォルトでは src 以下に置かれているので見てみましょう。

src/Lib.hs

module Lib
    ( someFunc
    ) where

someFunc :: IO ()
someFunc = putStrLn "someFunc"

src/Lib.hs の最後の2行が someFunc の実体になります。 someFunc = putStrLn "someFunc"someFunc = putStrLn "Hello World" という風に修正します。

そして stack runghcmain 関数を実行できます。

( stack exec my-project-exe でも同様の結果が得られます)

$ stack runghc app/Main.hs
Hello World

以上です。簡単でしたね。

おまけ

先ほど実行した app/Main.hs 、実は stack ghci でも実行できます。

$ stack ghci
The following GHC options are incompatible with GHCi and have not been passed to it: -threaded
Using main module: 1. Package 'my-project' component exe:my-project-exe with main-is file: /my-project/app/Main.hs
Configuring GHCi with the following packages: my-project
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Lib              ( /my-project/src/Lib.hs, interpreted )
Ok, modules loaded: Lib.
[2 of 2] Compiling Main             ( /my-project/app/Main.hs, interpreted )
Ok, modules loaded: Lib, Main.
*Main Lib> main
Hello World

GHCi はすごいH本を学習している方はおなじみですね。

なので、これから Stack を使ってすごいH本を学習しようと考えている人は、

  • 作成したパッケージは src 以下に置く
  • stack ghci で GHCi を起動した状態で、パッケージをロードして関数を実行する
  • main 関数のような I/O アクションを実行する場合は、stack runghc src/MyPackage.hs を使う

というスタイルがよいかもしれません(自分はこうやって学習していました)。

例えば src/Baby.hs 内の doubleMe という関数が使いたい場合は、次のように :l でパッケージのロードをすることで使えるようになります。

$ stack ghci
...
*Main Lib> :l src/Baby.hs
[1 of 1] Compiling Main             ( src/Baby.hs, interpreted )
Ok, modules loaded: Main.
*Main> doubleMe 9
18

参考文献