今日から始めるelm-lang

# elm-lang

http://elm-lang.org/

compileするとJSが吐き出されるalt JS的なもの。
文法がHaskellに近いらしい。
文法と関数の定義との関連が直感的にわかりやすいのが個人的に◎
言語について詳しく知りたい場合は、以下の記事がおすすめです。
http://qiita.com/mizchi/items/1c707342dd008af61118#_reference-7a151034909cd14c9e7d
http://qiita.com/mizchi/items/1c707342dd008af61118#_reference-7a151034909cd14c9e7d

# install

http://elm-lang.org/install

私はinstallerを使いました。
brewを使うと0.17がinstallされます。(最新は0.17.1)

# editor

vscodeでelmと検索してPluginをinstallすると捗ります。
公式ではsublimeおすすめとありましたが、頻繁に購入ダイアログが出てくるのと、vscode以上の機能がないのでやめました。
`code <fileName>`で開けるようにPATHを通すと捗ります。(コマンドパレットで`command`で検索すると出てくるはずです。)

# 入門

http://guide.elm-lang.org/

とりあえずここを読むだけで良い感じ。
適宜、coreやhtmlライブラリのコードを読むと捗ります。

## exerciseやってみた

ここの2つのダイスを回すものをやってみました
http://guide.elm-lang.org/architecture/effects/random.html

```elm:
module Main exposing (..)

import Html exposing (..)
import Html.App as Html
import Html.Events exposing (..)
import Random


main =
    Html.program
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }



-- MODEL


type alias Model =
    { dieFace : Int
    , twoFace : Int
    }


init : ( Model, Cmd Msg )
init =
    ( Model 1 1, Cmd.none )



-- UPDATE


type Msg
    = Roll
    | NewFace ( Int, Int )


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Roll ->
            ( model, Random.generate NewFace (Random.pair (Random.int 1 6) (Random.int 1 6)) )

        NewFace ( newFace, twoFace ) ->
            ( Model newFace twoFace, Cmd.none )



-- SUBCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.none



-- VIEW


view : Model -> Html Msg
view model =
    div []
        [ h1 [] [ text (toString model.dieFace) ]
        , h1 [] [ text (toString model.twoFace) ]
        , button [ onClick Roll ] [ text "Roll" ]
        ]
```

`Random.pair`を使う練習みたいですね。

HTTPのやつもやってみました
http://guide.elm-lang.org/architecture/effects/http.html

```elm
module Main exposing (..)

import Html exposing (..)
import Html.App as Html
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Http
import Json.Decode as Json
import Task


main =
    Html.program
        { init = init "cats"
        , view = view
        , update = update
        , subscriptions = subscriptions
        }



-- MODEL


type alias Model =
    { topic : String
    , gifUrl : String
    , errorMsg : String
    }


init : String -> ( Model, Cmd Msg )
init topic =
    ( Model topic "waiting.gif" ""
    , getRandomGif topic
    )



-- UPDATE


type Msg
    = MorePlease
    | FetchSucceed String
    | FetchFailed Http.Error
    | Name String


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        MorePlease ->
            ( model, getRandomGif model.topic )

        FetchSucceed newUrl ->
            ( Model model.topic newUrl "", Cmd.none )

        FetchFailed error ->
            case error of
                Http.Timeout ->
                    ( { model | errorMsg = "timeout error" }, Cmd.none )

                Http.NetworkError ->
                    ( { model | errorMsg = "network error" }, Cmd.none )

                Http.UnexpectedPayload payload ->
                    ( { model | errorMsg = "unexpected payload" }, Cmd.none )

                Http.BadResponse code status ->
                    ( { model | errorMsg = "badresponse" }, Cmd.none )

        Name newTopic ->
            ( { model | topic = newTopic }, Cmd.none )



-- VIEW


view : Model -> Html Msg
view model =
    div []
        [ input [ type' "text", placeholder "topic", onInput Name ] []
        , select [ onInput Name ] [ option [ value "cats", selected True ] [ text "cats" ], option [ value "dogs" ] [ text "dogs" ], option [ value "akb48" ] [ text "akb48" ] ]
        , button [ onClick MorePlease ] [ text "More Please!" ]
        , br [] []
        , h2 [] [ text model.errorMsg ]
        , img [ src model.gifUrl ] []
        ]



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.none



-- HTTP


getRandomGif : String -> Cmd Msg
getRandomGif topic =
    let
        url =
            "//api.giphy.com/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag=" ++ topic
    in
        Task.perform FetchFailed FetchSucceed (Http.get decodeGifUrl url)


decodeGifUrl : Json.Decoder String
decodeGifUrl =
    Json.at [ "data", "image_url" ] Json.string
```

selectの値取得は`onInput`でOKのようです。

## HTTP Package

`eml-package install evancz/elm-http`でインストールする。

## Resultについて

`Result.Result a b`からbを取得する場合、`Result.withDefault b (Result.Result a b)`のようにすればOK

```elm:例
$ elm-repl
> import String
> import Result
> Result.withDefault 1 (String.toInt "23") --- 第2引数はfunctionであること
```


# Project Setup

```bash
$ mkdir -p $HOME/dev/elm/sandbox
$ elm-package install
$ cd $HOME/dev/elm/sandbox
$ code ./
```

# Pakcage更新時にelm-reactorの挙動が変になる？

coreを4.0.1->4.0.2に更新した後、elm-reactorを動作させたら表示されなくなりました。
`elm-stuff`ディレクトリを削除して`elm-package install`したら戻りましたが、調査が必要ですね。

# まとめ

書いていてかなり楽しいですね。
特に関数の定義と実装が直感的なのが素晴らしいと思います。