Ubuntu、Haskellでwebアプリ手始め


Haskell!?
もちろん聞いたことはあるけど触ったことないです。。。
よし触ってみよう！

今回はHaskellで簡単なWebアプリを作ってみようと思います。
ほんと触りのところまでで恐縮ですが。。。

環境は下記です。
Haskell
Stack
Ubuntu 14.04
vagrant 2.0.0


#Stackのインストール

Stackとは
>
StackはHaskellプロジェクトを開発するためのクロスプラットフォームプログラムです。

>以下のような機能があります。
・隔離された場所にGHCを自動的にインストールする。
・プロジェクトに必要なパッケージをインストールする。
・プロジェクトを構築する。
・プロジェクトのテスト。
・プロジェクトのベンチマーク。

ほほう
まぁ入れてみよう。

`curl`か`wget`どちらか好きな方で

```sh
$ curl -sSL https://get.haskellstack.org/ | sh
```
or

```sh
$ wget -qO- https://get.haskellstack.org/ | sh
```

その後

#プロジェクト作成
```sh
$ stack new haskell_web_app(任意のプロジェクト名)
```

haskell_web_appというディレクトリが作られます。

中見てみましょう。

```sh
$ cd haskell_web_app
$ ls
```
このようなファイル構成ができあがってますね。

```
├── LICENSE
├── Setup.hs
├── app
│   └── Main.hs
├── haskell_web_app.cabal
├── src
│   └── Lib.hs
├── stack.yaml
└── test
    └── Spec.hs
```

ビルドしてみましょう。

```sh
$ stack build
```

#実行！
実行は`stack exec <プロジェクト名>-exe`

```sh
$ stack exec haskell_web_app-exe
someFunc
```

おお
sumeFuncとでました。

これは`app/Main.hs`のものが表示されていますね。

```app/Main.hs
module Main where

import Lib

main :: IO ()
main = someFunc
```
`app/Main.hs`の`main`という関数が実行されていますね。
`someFunc`という関数を呼び出しているようです。
`someFunc`関数はインポートしている`Lib`パッケージのものです。
`src/Lib.hs`をみてみましょう。

```src/Lib.hs
module Lib
    ( someFunc
    ) where

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

`someFunc`いましたね。
こいつが表示されていました。

#waiをimport
さて、今回の目的はwebアプリを作ることなので、
`wai`というものをインポートしてみましょう。

えーっとなになに、`package.yaml`に追加したいモジュールを記載するとビルド時に`<プロジェクト名>.cabal`にコンバートされ、インストールしてくれると。。。

よし、では`package.yaml`に追加しよう。

```package.yaml
dependencies:
- base >= 4.7 && < 5
- wai
```

`wai`を追加しました。

ビルドしてみましょう。

```sh
$ stack build
'parse': (<unknown>): control characters are not allowed at line 0
```

おや、、、何か使い方違うのかな。。。
テストしてみたところ、改行一行だけいれてビルドしても同じエラーでした。
なんだ！？文字コードか！？vagrant上での開発が影響しているのか。。。
ということで、Windowsとの共有フォルダを変更することにしました。

```ruby
  config.vm.synced_folder "./app", "/home/vagrant/haskell/haskell_web_app/app"
  config.vm.synced_folder "./src", "/home/vagrant/haskell/haskell_web_app/src"
  config.vm.synced_folder "./test", "/home/vagrant/haskell/haskell_web_app/test
```

今回は`haskell`という名前で共有フォルダを作り、まるっと共有していたのですが、`app`,`src`,`test`以下だけを共有することにして、`package.yaml`はubuntu側で`vim`で編集してみました。
するとうまくいきました！！
文字コードっぽいですね。。。
あ、共有フォルダを変更した際は`vagrant reload`を忘れずに。

#Main.hs編集
さぁ、やっと`wai`をインポートできたのでMain.hsを編集していきましょう。

[wai: Web Application Interface.](https://hackage.haskell.org/package/wai/ "タイトル")

waiのサイトに簡単なサンプルがあるのでいれてみましょう。
ふむふむ、`warp`と`http-type`というパッケージもインストールする必要があるみたいですね。
package.yamlに追加。

```package.yaml
dependencies:
- base >= 4.7 && < 5
- wai
- warp
- http-types
```
ホスト名とポートだけ修正しています。

```Main.hs
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.HTTP.Types
import Network.Wai.Handler.Warp (run)

app :: Application
app _ respond = do
    putStrLn "I've done some IO here"
    respond $ responseLBS
        status200
        [("Content-Type", "text/plain")]
        "Hello, Web!"

main :: IO ()
main = do
    putStrLn $ "http://192.168.33.10:3000/"
    run 3000 app
```

#実行！
ビルドして実行してみましょう。
```
$ stack excec haskell_web_app-exe
http://192.168.33.10:3000/
```

よし、Webから`http://192.168.33.10:3000`にアクセスしてみましょう。

ブラウザに`Hello, Web!`と出ていたら成功です。

#まとめ
今回は初めてHaskellに触ってみましたが、正直コードの中身については完全には理解できておりません。
Haskellを理解するにはまだ時間が必要そうです。。。
今後も勉強していきたいと思います。

以上、ありがとうございました。