ElmでBrowserモジュールを使って「Hello World!!」する

最近ようやくElmを少し使えるようになってきました。
ちょっとだけ複雑なプログラムを書けるくらいにはなったと思います。

やっぱり関数型は慣れるのが難しくて公式の簡単なサンプルを理解するのも一苦労です。
なので、自分の学びをここらで一旦まとめてみます。

もし自分の理解が間違っているところがあれば指摘お願いします。

# 今回作ったもの

「Hello World!!」です。
そうです。あえて作らなくても公式にサンプルあります。 → https://elm-lang.org/examples/hello

でも、そうじゃ無い。

今回はBrowserモジュールを使って作りたいんです。
どうやら公式のサンプルをみる限りほとんどでBrowserモジュールなるものを使っています。
かなり浅はかな認識ですが、Elmでプログラム組むならBrowserモジュールがとりあえず必要なようです。

なので、あえてBrowserモジュールを使った上で「Hello World!!」を作りたいと思います。

# 早速ですが完成品

早速ですが、完成品です。ここ([Try Elm!](https://elm-lang.org/try))で貼り付けて動作を試せます。

```elm
-- 例のBrowserモジュール
import Browser
-- HTMLタグを出力するためのモジュール
import Html exposing (..)


-- MAIN

-- メイン関数
main =
  Browser.sandbox
    { init = init
    , update = update
    , view = view
    }


-- MODEL

-- モデル(Model)を定義
type alias Model =
  { hello : String }

-- モデルを初期化
-- model.helloに"Hello World!!"を設定する
init : Model
init = Model "Hello World!!"


-- UPDATE

-- メッセージ(Msg)を定義
-- この例では更新処理をしないので、メッセージが渡ってくることはない
-- なので、MsgはNoneということにしておく(Noneに特に意味はない)
type Msg = None

-- ページ更新処理を定義
-- この例では更新処理をしないので、そのままmodelを返すことにしとく
update : Msg -> Model -> Model
update msg model = model


-- VIEW

-- ページ描画処理を定義
-- この例では、model.helloの中身を表示するのみ
view : Model -> Html Msg
view model =
  text model.hello
```

# 解説

## モジュールの読み込み

まずはモジュールの読み込み部分です。

```elm
import Browser
```

これは例のやつです。残念ながらこれが何かということを説明できるレベルにはまだなってません。今はおまじないとして覚えておくことにします。

```elm
import Html exposing (..)
```

これはHTMLタグを出力する関数をまとめたモジュールです。
後述しますが、 `text model.hello` とかやってるところの `text` がこのモジュールの関数です。
ちなみに `exposing (..)` の部分はこのモジュールの全ての関数を読み込むことを表しています。
`exposing (text)` と書けばtext関数だけを読み込むことも可能です。
とりあえず個別に読み込むのは面倒なので全部読み込みます。

## メイン関数

メイン関数です。

```elm
main =
  Browser.sandbox
    { init = init
    , update = update
    , view = view
    }
```

ここもおまじないとして理解しておきます。
ちなみに、 `sandbox` の他には `element` `document` `application` などがあるようです。
詳しいことはこちらの記事がおすすめです。

[ElmのBrowser.*の使い分け](https://qiita.com/miyamo_madoka/items/aa499d2f0fa756065a06)

## モデルの定義と初期化

次にモデルの定義と初期化を行います。

```elm
type alias Model =
  { hello : String }
```

モデル(Model)のタイプエイリアス(型の別名)を定義しています。
タイプエイリアスについては公式(訳)の解説が分かりやすかったです。

[型の別名（タイプエイリアス）](https://guide.elm-lang.jp/types/type_aliases.html)

あと、 `{ hello : String }` というような書き方はレコードと呼ぶらしいですね。これも公式(訳)のやつ。(公式の日本語訳ページはElm-jpコミュニティさんによるものなんですね。お世話になってます。)

[言語の基礎 - レコード](https://guide.elm-lang.jp/core_language.html#%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89)

ここでModelという名前で定義したレコードのhelloという要素に "Hello World!!" が入ることになります。

```elm
init : Model
init = Model "Hello World!!"
```

さて早速さっき定義したモデルに "Hello World!!" という文字列を代入しています。
代入しているというより、 "Hello World!!" という文字列が入ったModel型の変数を生成しているというのが正しいのかもしれませんね。関数型の難しいところです。

## 更新処理の定義

次に更新処理の定義を行います。
とは言っても今回の例では更新処理はないので、極力無駄な記述は避けます。

```elm
type Msg = None
```

メッセージ(Msg)はページ更新の際に渡される値です。
ただ、今回は更新処理がないためMsgはNoneとしておきます。
Noneという単語に特に意味はないので、 `type Msg = Hoge` とかなんでもいいです。だって今回使わないので。
でも、定義しないと怒られるので書いておきます。

```elm
update : Msg -> Model -> Model
update msg model = model
```

ここは更新処理を記述する部分です。
更新処理はメッセージとモデルを受け取って、受け取ったメッセージに基づく処理を行い、新たなモデルを生成するという処理を行います。
ただ、今回は更新処理がないためモデルを更新する必要がありません。なので、受け取ったままのモデルを返すという風に書いておきます。
update関数の定義は行うけどこの例でこの関数が呼ばれることはありません。

## ページ描画処理の定義

最後にページ描画処理です。

```elm
view : Model -> Html Msg
view model =
  text model.hello
```

ここはモデルの中身に応じてHTMLを出力するという処理です。
text関数を使ってmodel.helloの中身の文字列(つまり "Hello World!!" )を表示するHTMLを出力しています。

# 全体の流れ

メイン関数をみるとinit,update,viewの関数が実行されることがわかります。

```elm
main =
  Browser.sandbox
    { init = init
    , update = update
    , view = view
    }
```

まず最初にinit関数が呼ばれ、初期状態のモデルを生成します。

```elm
init : Model
init = Model "Hello World!!"
```

そして次にview関数が呼ばれ、モデルを元にHTMLを出力し、ページを描画します。

```elm
view : Model -> Html Msg
view model =
  text model.hello
```

これで終わりです。

本当はこのあとユーザーがページに大して行ったアクションに応じてupdate関数が呼ばれて更新処理が行われるのですが、今回の例では文字列を出力しただけなのでユーザーはアクションの起こしようがありません。なので、更新処理は行われません。

ちなみに、次回はこれからさらにアクションを起こしてupdate関数まで実行させてみます。

[ElmでBrowserモジュールを使って「Hello World」をシャウトする](https://qiita.com/akkey2475/items/8c111accdafdc2c4f2d8)

# 最後に

実際今回のプログラムの出力結果は公式のサンプルとほぼ同じです。
なので、本当はこれだけで事足ります。

```elm
import Html exposing (text)

main =
  text "Hello World!!"
```

あえてBrowserモジュールを使って回りくどく書いてみました。
本来こうやって書く意味はないですが、仕組みを理解する上ではこういう書き方をあえてしてみるのはとても有効だと思います。
公式も十分細かく段階別にサンプルを用意してくれてますが、自分みたいなまだ理解度の低い人から見るといきなりレベルめっちゃ飛んだように感じちゃうんですよね。いつもその中間レベルのサンプルコードください！って思います。
今回作ったものが誰かが欲していた中間レベルのサンプルコードになれたら幸いです。