Elm初心者がElm Packagesを使えるようになるまで

##ごあいさつ

皆さんはじめまして。[@enma](https://twitter.com/enma/)と申します。
[Elm](http://elm-lang.org/)に興味があってここをご覧になられている方と、そうでない方もおられると思いますが、[Elm Advent Calendar 2017](https://qiita.com/advent-calendar/2017/elm)の16日目の記事です。
一応断っておきますと、筆者はこれまで関数型言語での実装経験はありませんし、Webページ制作の経験もほとんどありません。しかしながら、Elmは純粋関数型言語としての魅力があり、またWebページ作成の観点からもかなり実用的な言語であると思いました。
初心者なりにElmの魅力を伝えられれば、更なるコミュニティの拡大にも繫がりますし、今回僭越ながら**「Elm初心者がElm Packagesを使えるようになるまで」**というタイトルで書かせて頂いております。どうぞ続けてご覧頂けると嬉しいです。

##Elmことはじめ
筆者はこれまで関数型プログラミングに縁が無く、[@ababup1192さんの記事](https://qiita.com/ababup1192/items/d6ca1af6efcbac8d550f)をきっかけにElmの学習を始めました。今回は、これまで筆者が学習した内容と、Elmのコードを動作させる環境構築の手順を説明します。その後、Ellieと呼ばれるオンライン上のWebサービスを使って、Elmのプログラムを動作させるまでが記事の内容となります。

Elmは、HTMLやJavaScript、CSSで構成されたWebアプリケーションを、Elmのみで簡単に生成することができるプログラミング言語です。
`elm-make`を実行することで、Elmで書かれたファイル（.elm）の依存関係を解決して(すなわち`elm-package.json`の作成が為されて)コンパイルが行われ、HTMLやJavaScriptのファイルを生成することが可能です。
筆者は恥ずかしながらHTMLやJavaScriptが使えないので、Elmさえ覚えれば(痒い所に手は届くかは置いておいて)Webアプリが作れるという点はかなり魅力的です。
※ CSSに関しては、例えば[elm-css](https://github.com/rtfeldman/elm-css)がありました。また新しく出された[@arowMさんの記事](https://qiita.com/arowM/items/50f40b4e78133b7ef00f)も参考になりそうです。



 また、Elmは以下のような特徴を持っています。

・純粋関数型言語であり、静的型付き言語である
・型についてはかなり厳密なイメージ（その分実行時エラーが起こりにくい）
・他言語と比較して、シンプルなコード記述で求める機能の実装が可能
・型推論、型検査の機能を持ち、Haskell由来の強力なパターンマッチを有する

Elmは現在、[The Elm Architecture](https://github.com/evancz/elm-architecture-tutorial)という設計思想に則りWebアプリケーションを構成するのが定石とされています。リリースバージョンはまだ0.18ということもあって、破壊的なパラダイムシフトが行われる可能性もありますが、The Elm Architectureはシンプルかつ明快な思想であることから、廃止される可能性は低いと思っています。

The Elm Architectureは、`beginnerProgram`を使う方針と`program`を使う方針の2通りがあります（詳しくは[Elm PackagesのProgramの項](http://package.elm-lang.org/packages/elm-lang/html/2.0.0/Html)を参照）。筆者は取っ掛かりとして、今回は`beginnerProgram`を使う方法を中心に学習しました。
beginnerProgramを使用するには、model/view/msg/updateという4種類の関数と型を用意します。

```Elm:beginnerProgram
beginnerProgram
    :  { model : model, view : model -> Html msg, update : msg -> model -> model }
    -> Program Never model msg
```
それぞれの関数/型のイメージは、Webアプリケーションの場合
・`model`：Webアプリを構成する要素を定義し、それらの状態を示す（したがって初期状態の定義が必要）
・`view`：modelをhtmlに変換する関数
・`msg`：何らかのイベント(例えばボタンクリック)を示す
・`update`：msgが投げられた際に、msgと元のmodelから新たなmodelを作成する

です。Elmの構文はHaskellライクのようですが、Haskell未経験の方はおそらく私同様、少し面食らうでしょう。まずは、Elmの文法/構造についてWeb上の入門記事を見ながら、目で追って確認していくのが良いです。

文法学習にはおそらく[Elmチートシート](https://github.com/izdi/elm-cheat-sheet)を見るのが手っ取り早いですが、英語に抵抗のある方は[Elmチュートリアル(日本語版)の基本の項](https://www.elm-tutorial.org/jp/)や、[プログラミング言語Elmの薄い本のPartIIの項](https://giisyu.gitbooks.io/elm_usui_book/content/src/Elm/aboutElm.html)を眺めてみてください。
その後、例えば[@mather314](https://qiita.com/mather314)さんの記事「[Elm 0.18 入門 (1)カウントアプリを作ってみる]
(https://qiita.com/mather314/items/e9e08960d91b187652e5)」を読めば導入が割とスムーズです。

更には、[Elm Packages](http://package.elm-lang.org/)内のPopular Packagesを徐々に見ていくとElmはデフォルトで豊富な機能を用意してくれている事が分かります。パッケージを`import`すれば、パッケージの中で既に用意されている関数を利用することが出来ます。
[Elm Core Libraries](http://package.elm-lang.org/packages/elm-lang/core/latest)や[HTML for Elm](http://package.elm-lang.org/packages/elm-lang/html/latest)はおそらく必修に近いレベルであり、Webページ作成を行う際にこれらは使いこなせるようになっておく必要があると感じました。

Elmの文法については割愛させて頂きますが、個人的に少し悩み、つまづきポイントだと感じた点を以下にいくつか挙げました。
**➀ typeとtype aliasの使い所のイメージ**
**➁ Elm Packagesの個々のパッケージの中で定義されている関数の見方**
**➂ 複数の型や値を持つものから、特定のものを取り出す方法**

**➀ typeとtype aliasの使い所のイメージについて**
`type`は新しい型を定義したい時に使う、`type alias`はレコード型の定義もしくは既存の型に別名を付けたい時に使う、ということで意味は理解できるのですが、同じ"type"という語を使っていることもあり少し混乱しました。混乱の元となったのはおそらく、ユニオン型(`Union Types`)があるせいです。ユニオン型は、以下のように型の集約が可能です。

```Elm:ユニオン型による定義
type Fruits = Orange | Melon | Apple
```
コード内の`|`記号が"OR"という意味ではないということに注意してください。上の例は、`Fruits`が`Orange`か`Melon`か`Apple`のいずれかの値を取り得るという定義です。ユニオン型は列挙した値のいずれかになるというイメージをしっかりと持った方が、理解がしやすくなると思いました。

ユニオン型ではない型定義の場合、

```Elm:typeで新たな型を定義する
--type 型名 = データ構築子 （定義に必要な既存の型）...
type Msg = Get String
```
のように、型名とデータ構築子は大文字から始まる必要があること、必ず他と被らない新しいデータ構築子も定義される必要があることに注意して新たな型を定義してください。

また、`type alias`で定義された型変数は以下のようなイメージを持つと分かりやすいです。


```Elm:型エイリアス
-- 整数型 Intに"金額"という意味を付加することで扱いやすくする
type alias Amount =  Int


-- レコード型を用いて"Player"型に"id"と"name"という複数の属性を付加させる
type alias Player =
    { id : Int
    , name : String
    }
```


**➁ Elm Packagesの個々のパッケージの中で定義されている関数の見方について**
ひどいものだと`->`が何個も登場するものがあります。

```Elm:Html.Lazy
lazy3 : (a -> b -> c -> Html msg) -> a -> b -> c -> Html msg
```
どんなに`->`が多くても結局、戻り値は一つしかないので
・右端の型にたどり着くまでの型は全て引数とみなす
・パイプ演算子や部分適用などを駆使して、戻り値が右端の最後の型になるように `->` で繋げて型を定義する
という見方が良いかなと思われます。

**➂ 複数の型や値を持つものから、特定のものを取り出す方法について**
名前付き関数の定義の際、最初の行には関数のシグネチャを書きます（関数の意図を明確にするために記述することを推奨）。次の行で`関数名 引数1 引数2 ... = 式`という構造を用いて、関数内の全体をifで切り分ける代わりに、特定の引数を指定して関数を分割定義できます。このような書き方はパターンマッチと呼ばれ、意外と習熟が必要なところで難しいです。

```Elm:パターンマッチの仕方
type alias Amount =
    Int


type Dollar
    = Dollar Amount


-- "Dollar"型から"Amount"型を取り出すmoney関数
money : Dollar -> Int
money (Dollar amount) =
    amount

```

`case`式によるパターンマッチ以外にも、上記のように引数によるパターンマッチも可能です。money関数の定義の２行目で、"amount"という引数を用いて"Dollar"型から"Amount"型を取り出すことを実現しています。上記を書くに当たり、[@ababup1192さんの記事](https://qiita.com/ababup1192/items/d6ca1af6efcbac8d550f)をはじめ、[株式会社ガラパゴスさんの記事](http://gtech.hatenablog.com/entry/2016/10/21/110212)や[@7shiさんの記事](https://qiita.com/7shi/items/145f1234f8ec2af923ef)も参考にさせて頂きました。

※ `type A = Hoge Int`の形なら引数のパターンマッチが可能だが、`type B = Hoge Int | Foo String`の場合`case`式を必ず使わないといけないので注意すべき、とのご指摘を@ababup1192さんから頂きました。ありがとうございます。



##コードの実行環境について
それでは、実際にコードを実行する環境についての話に進みます。
Elmのコードを実行するには、まずNode.jsのインストールが必要です。Node.jsはサーバーサイドJavaScriptの実行環境です。Node.jsはNode.jsのモジュールを管理するためのツール「npm」を用いて`npm i`でインストールします(`npm i`が通らない場合、npm自体のヴァージョンが古い可能性があります。筆者はnpmのバージョンが古かったので`npm install -g npm`で上げました)。
また、Elmのヴァージョンは`0.18.0`です(`Elm -v`コマンドで確認できます)

※1.筆者の使用PCはSurface Pro4、OSはWindows10 Pro RS2です
※2.万が一`npm`が使えない場合、MacとWindowsは、公式サイトからインストーラが提供されていますのでそちらを使用してください

インストールできたかどうかは、コマンドライン上で`elm -v`や`elm make -h`を叩いたりして、何らかの実行結果が返ってくれば成功です。筆者の環境ではGit bash、Command prompt、WSL(Windows Subsystem for Linux)でいずれも動作可能でした。

`elm-package install elm-lang/html`で`Html`パッケージ(パッケージはPythonで言うところのモジュールのイメージです)をインストールした後、適当なコード(例えば以下)を書いて`elm-make hello.elm`を実行すればコンパイル成功です。

```Elm:hello.elm
import Html exposing (text)

main =
  text "Hello World"
```


また、記述したコードが特定のパッケージに依存している場合、`elm-package.json`が置いてあるフォルダ上で`elm-package install`を実行すれば、`elm-package.json`に記述してある依存ライブラリを自動でインストールしてくれます。

##コードの記述環境について
Elmを書くエディタは`Visual Studio Code`を使用しています。VS CodeにはElmプラグインがあり、導入することでElmが非常に見やすく、書きやすくなります。中でも`elm-format`という機能はElmの独特な(or Haskellライクな)コードの整形を半自動で行ってくれるのでおすすめです。
`npm`が使えれば導入は問題ないと思われますが、例えばプロキシでネットワークが制限されている場合、`npm`を使ったインストールができないことがあります。`Windows`の場合は、`elm-format.exe`がリリースされています(以下はファイルのリンクです)
https://github.com/avh4/elm-format/releases/download/0.7.0-exp/elm-format-0.18-0.7.0-exp-win-i386.zip 
`elm-make.exe`や`elm-repl.exe`があるフォルダに`elm-format.exe`を格納したあと(筆者はGit bashを入れていたので、VS Code上で`which`コマンドを実行して`elm-make.exe`が置いてある場所を確認しました)、ワークスペース設定のパス指定のところで

```
"elm.formatCommand":"elm-format"
```
と記述すれば、新たにパスを通さずとも`Shift+Alt+F`コマンドによるコード整形が機能するようになります。


書いたコードの実行結果は、VS Codeでも確認することは出来ますが、他にもElmに標準で用意されている`elm-reactor`(HTTPサーバーを通して、書いたプログラムの実行結果をブラウザを見ながら確認できる)や、対話環境としての`elm-repl`(式を実行して値や型の確認が可能)があります。

また、筆者は勉強する中で[Ellie](https://ellie-app.com/) というElm専用のWebサービスがあることを知りました。
Ellieはオンライン上のElmのテキストエディタで、コードを書いてコンパイルすることで、Webページがどのように表示されるか確認することができます。Elmのパッケージ([Elm Packages](http://package.elm-lang.org/))も追加できるので、小規模な開発環境としては有用だと思います。Pythonで言うところのJupyter Notebookに近い使い勝手の良さですね。詳しくは[Elm 0.18 入門 (1)カウントアプリを作ってみる]
(https://qiita.com/mather314/items/e9e08960d91b187652e5)のページを参考にしてください。

##Ellieを使ってElm Packagesのコードを実行してみる

試しに`elm-colorpicker`というパッケージを使ってコードを書き、コンパイルを通してみましょう。[Elm Packages](http://package.elm-lang.org/)には有志が作成したパッケージが数多くあり、`elm-colorpicker`もその中の一つです(日本だとジンジャーさんという方が数多くパッケージを公開されています(http://jinjor-labo.hatenablog.com/)

GoogleChromeで[Ellie](https://ellie-app.com/)を開いた後（筆者の環境では、IEだとうまく動作しませんでした）、左側のSearch for packagesでelm-colorpickerと入力し、パッケージをインストールしてください。その後、[Elm Packages](http://package.elm-lang.org/)のSearchにelm-colorpickerと入力し、パッケージの説明ページを見てください。Exampleという項におよその使い方が書かれてあります。これを参考にしながら、beginnerProgramを使ってEllie上でプログラムを実行してみましょう。
誤植を訂正しつつ、beginnerProgramを使ってEllie上で最低限動作するプログラムを以下に書きました。

```Elm:elm-colorpicker
module Main exposing (..)

import ColorPicker exposing (State, empty, view)
import Html exposing (Html, beginnerProgram)
import Color


main : Program Never Model Msg
main =
    Html.beginnerProgram
        { model = init
        , update = update
        , view = view
        }


type alias Model =
    { colour : Color.Color
    , colorPicker : ColorPicker.State
    }


init : Model
init =
    { colorPicker = ColorPicker.empty
    , colour = Color.rgb 255 0 0
    }


type Msg
    = ColorPickerMsg ColorPicker.Msg


update : Msg -> Model -> Model
update message model =
    case message of
        ColorPickerMsg msg ->
            let
                ( m, colour ) =
                    ColorPicker.update msg model.colour model.colorPicker
            in
                { model
                    | colorPicker = m
                    , colour = colour |> Maybe.withDefault model.colour
                }


view : Model -> Html Msg
view model =
    ColorPicker.view model.colour model.colorPicker
        |> Html.map ColorPickerMsg
```
ページの右上辺りにカラーピッカーが現れればコンパイル成功です。
本当は、Googleのcolorpickerのように、コンターだけではなくカラーコードも表示できるようにしたかったのですが、経験不足で今回は実装できませんでした。今後の課題とさせて頂きます。

##あとがき
Elm初心者として、Elm導入からサンプルコード実行までの流れを記事にしてみました。The Elm Architectureという分かりやすい設計思想を持ち、関数型言語として簡潔な記述が可能であるという点は十分魅力的なポイントです。教育的かつ実用的であり、周りの方にも勧めやすい言語である気がします。Elmをベースにして、関数型プログラミングについての知識を更に深めていきたいです。ここまで読んで頂き、ありがとうございました！