2017年5月13日土曜日

HaskellでHello World、Stack使ってやってみた。

プログラミング言語始めるときはやっぱりHello Worldですよね。
と言う訳で、正攻法ではないかもですが、Stackを使ってHello Worldやってみました。

参考
 The Haskell Tool Stack - Install/upgrade
 The Haskell Tool Stack - User guide

環境
 vagrantを使用して環境を作成。(以下、使用したbox)
  config.vm.box = "geerlingguy/centos7"

ログイン後、とりあえずyum update
$ sudo yum update -y
    ~~~~略~~~~

stackインストール
$ curl -sSL https://get.haskellstack.org/ | sh
    ~~~~略~~~~
    Stack has been installed to: /usr/local/bin/stack

インストール確認
$ stack --version
    Version 1.4.0, Git revision e714f1dd3fade19496d91bd6a017e435a96a6bcd (4640 commits) x86_64 hpack-0.17.0

プロジェクト作成
$ stack new helloworld new-template
    Downloading template "new-template" to create project "helloworld" in helloworld/ ...

    The following parameters were needed by the template but not provided: author-email, author-name, category, copyright, github-username
    You can provide them in /home/vagrant/.stack/config.yaml, like this:
    templates:
      params:
        author-email: value
        author-name: value
        category: value
        copyright: value
        github-username: value
    Or you can pass each one as parameters like this:
    stack new helloworld new-template -p "author-email:value" -p "author-name:value" -p "category:value" -p "copyright:value" -p "github-username:value"

    Looking for .cabal or package.yaml files to use to init the project.
    Using cabal packages:
    - helloworld/helloworld.cabal

    Selecting the best among 10 snapshots...

    Downloaded lts-8.13 build plan.
    Selected mirror https://s3.amazonaws.com/hackage.fpcomplete.com/
    Downloading root
    Selected mirror https://s3.amazonaws.com/hackage.fpcomplete.com/
    Downloading timestamp
    Downloading snapshot
    Downloading mirrors
    Cannot update index (no local copy)
    Downloading index
    Updated package list downloaded
    Populated index cache.
    * Matches lts-8.13

    Selected resolver: lts-8.13
    Initialising configuration using resolver: lts-8.13
    Total number of user packages considered: 1
    Writing configuration to file: helloworld/stack.yaml
    All done.

作成されたプロジェクトを確認
$ ls
    helloworld

移動
$ cd helloworld/

セットアップ
$ stack setup
    Preparing to install GHC to an isolated location.
    This will not interfere with any system-level installation.
    Downloaded ghc-8.0.2.
    Installed GHC.
    stack will use a sandboxed GHC it installed
    For more information on paths, see 'stack path' and 'stack exec env'
    To use this GHC and packages outside of a project, consider using:
    stack ghc, stack ghci, stack runghc, or stack exec

ビルド?
$ stack build
    [1 of 2] Compiling Main             ( /home/vagrant/.stack/setup-exe-src/setup-mPHDZzAJ.hs, /home/vagrant/.stack/setup-exe-src/setup-mPHDZzAJ.o )
    [2 of 2] Compiling StackSetupShim   ( /home/vagrant/.stack/setup-exe-src/setup-shim-mPHDZzAJ.hs, /home/vagrant/.stack/setup-exe-src/setup-shim-mPHDZzAJ.o )
    Linking /home/vagrant/.stack/setup-exe-cache/x86_64-linux/tmp-Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 ...
    helloworld-0.1.0.0: configure (lib + exe)
    Configuring helloworld-0.1.0.0...
    helloworld-0.1.0.0: build (lib + exe)
    Preprocessing library helloworld-0.1.0.0...
    [1 of 1] Compiling Lib              ( src/Lib.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Lib.o )
    Preprocessing executable 'helloworld-exe' for helloworld-0.1.0.0...
    [1 of 1] Compiling Main             ( app/Main.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/helloworld-exe/helloworld-exe-tmp/Main.o )
    Linking .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/helloworld-exe/helloworld-exe ...
    helloworld-0.1.0.0: copy/register
    Installing library in
    /home/vagrant/haskell/helloworld/.stack-work/install/x86_64-linux/lts-8.13/8.0.2/lib/x86_64-linux-ghc-8.0.2/helloworld-0.1.0.0-44GC3BWnM1QFjPMM1ngxcQ
    Installing executable(s) in
    /home/vagrant/haskell/helloworld/.stack-work/install/x86_64-linux/lts-8.13/8.0.2/bin
    Registering helloworld-0.1.0.0...

実行してみる。
$ stack exec helloworld-exe
    someFunc

テスト?
$ stack test
    helloworld-0.1.0.0: unregistering (components added: test:helloworld-test)
    helloworld-0.1.0.0: build (lib + exe + test)
    Preprocessing library helloworld-0.1.0.0...
    Preprocessing executable 'helloworld-exe' for helloworld-0.1.0.0...
    Preprocessing test suite 'helloworld-test' for helloworld-0.1.0.0...
    [1 of 1] Compiling Main             ( test/Spec.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/helloworld-test/helloworld-test-tmp/Main.o )
    Linking .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/helloworld-test/helloworld-test ...
    helloworld-0.1.0.0: copy/register
    Installing library in
    /home/vagrant/haskell/helloworld/.stack-work/install/x86_64-linux/lts-8.13/8.0.2/lib/x86_64-linux-ghc-8.0.2/helloworld-0.1.0.0-44GC3BWnM1QFjPMM1ngxcQ
    Installing executable(s) in
    /home/vagrant/haskell/helloworld/.stack-work/install/x86_64-linux/lts-8.13/8.0.2/bin
    Registering helloworld-0.1.0.0...
    helloworld-0.1.0.0: test (suite: helloworld-test)

    Progress: 1/2Test suite not yet implemented

    Progress: 1/2

src/Lib.hsの内容確認
$ cat src/Lib.hs
    module Lib
        ( someFunc
        ) where

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

src/Lib.hsを変更する
someFunc = putStrLn "someFunc" を
someFunc = putStrLn "Hello World!" に変更する
$ vi src/Lib.hs
    module Lib
        ( someFunc
        ) where

    someFunc :: IO ()
    someFunc = putStrLn "Hello World!"

再ビルド
$ stack build
    helloworld-0.1.0.0: unregistering (local file changes: src/Lib.hs)
    helloworld-0.1.0.0: build (lib + exe)
    Preprocessing library helloworld-0.1.0.0...
    [1 of 1] Compiling Lib              ( src/Lib.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Lib.o )
    Preprocessing executable 'helloworld-exe' for helloworld-0.1.0.0...
    [1 of 1] Compiling Main             ( app/Main.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/helloworld-exe/helloworld-exe-tmp/Main.o ) [Lib changed]
    Linking .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/helloworld-exe/helloworld-exe ...
    helloworld-0.1.0.0: copy/register
    Installing library in
    /home/vagrant/haskell/helloworld/.stack-work/install/x86_64-linux/lts-8.13/8.0.2/lib/x86_64-linux-ghc-8.0.2/helloworld-0.1.0.0-44GC3BWnM1QFjPMM1ngxcQ
    Installing executable(s) in
    /home/vagrant/haskell/helloworld/.stack-work/install/x86_64-linux/lts-8.13/8.0.2/bin
    Registering helloworld-0.1.0.0...

テストもとりあえず
$ stack test
    helloworld-0.1.0.0: unregistering (components added: test:helloworld-test)
    helloworld-0.1.0.0: build (lib + exe + test)
    Preprocessing library helloworld-0.1.0.0...
    Preprocessing executable 'helloworld-exe' for helloworld-0.1.0.0...
    Preprocessing test suite 'helloworld-test' for helloworld-0.1.0.0...
    helloworld-0.1.0.0: copy/register
    Installing library in
    /home/vagrant/haskell/helloworld/.stack-work/install/x86_64-linux/lts-8.13/8.0.2/lib/x86_64-linux-ghc-8.0.2/helloworld-0.1.0.0-44GC3BWnM1QFjPMM1ngxcQ
    Installing executable(s) in
    /home/vagrant/haskell/helloworld/.stack-work/install/x86_64-linux/lts-8.13/8.0.2/bin
    Registering helloworld-0.1.0.0...
    helloworld-0.1.0.0: test (suite: helloworld-test)

    Progress: 1/2Test suite not yet implemented

    Progress: 1/2

実行してみる
$ stack exec helloworld-exe
    Hello World!

Hello Worldの完成!


helloworldアプリの動き
たぶん以下の流れで動いているのかな?
    1. helloworld実行
    2. app/Main.hs が呼ばれる
        Main.hsにはLibがimportされている
    3.Main.hsからsomeFunc関数が呼ばれる
    4.Hello World!が表示される

 Main.hsの中身
 $ cat app/Main.hs
     module Main where

     import Lib

     main :: IO ()
     main = someFunc


とりあえずHello Worldはあっさり出来ました。
Hello Worldだしあっさりしてて当然かな?

ちなみに参考にしたUser guideでは、
ビルド時の依存関係やらなんやらの説明が主でした。
またの機会にちゃんとやりたいと思います。

今回は以上です。

0 件のコメント:

コメントを投稿