ElmでCRUDを作る - 其のR

Elmの良いところってそこそこ高度な動きをするものをすぐ作れるところだと思います。
モチベーション上がるし関数型を学ぶには良い教材のような気がします。慣れるまでは大変でしたが、今は書いててとても楽しいです。
勉強のために作ったサンプルコードがもうちょいあるのであと何記事分か書いてみる予定です。

続きの記事も書きました。

ElmでCRUDを作る - 其のR (この記事)

[ElmでCRUDを作る - 其のC ①](https://qiita.com/akkey2475/items/a256ae33449e06d0d370)

[ElmでCRUDを作る - 其のC ②](https://qiita.com/akkey2475/items/32cdc207df94d7135cc3)

[ElmでCRUDを作る - 其のD](https://qiita.com/akkey2475/items/3f070309d04253febac4)

# 今回作ったもの

TODOリストです。
すでにたくさんサンプルコード有るわ！って感じですが、同じTODOリストでも違う実装のサンプルコードはいくらあっても良いものです。(と思う）

最初はリストを表示するだけのもの(Read)から、リストの追加(Create)、リストの削除(Delete)と段階を追って実装していきます。
ちなみに実は編集機能のU(Update)はまだ自分には難しくて作れてないので今回実装はありません。ごめんなさい。

この記事ではCRUDのR(Read)をまず実装しようと思います。
モデルのリストをリストタグで表示するだけです。

# 完成品

とりあえず、完成品こちらです。ここ([Try Elm!](https://elm-lang.org/try))で貼り付けて動作を試せます。

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


-- MAIN

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


-- MODEL

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

-- モデルを初期化
-- model.listに任意のリストを設定する
init : Model
init = Model ["item1", "item2", "item3"]


-- UPDATE

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

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


-- VIEW

-- ページ描画処理を定義
-- この例では、model.listの中身をリストで表示する
view : Model -> Html Msg
view model =
  makeList model.list


-- ユーザー定義関数

-- リストを出力する
makeList : List String -> Html Msg
makeList list =
  ul [] ( List.map makeListItem list )

-- リストアイテムを出力する
makeListItem : String -> Html Msg
makeListItem itemText =
  li [] [ text itemText ]
```

# 解説

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

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

モジュールはBrowserとHtmlを使います。

## メイン関数

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

今回はBrowser.sandboxを使用します。

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

```elm
type alias Model =
  { list : List String }

init : Model
init = Model ["item1", "item2", "item3"]
```

モデルはList String型のlistという要素を一つ持つレコードとして定義します。
初期値には、とりあえず３つの要素を持つリストを指定してみました。

## 更新処理の定義

```elm
type Msg = None

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

更新処理は今回使わないので、Msgには適当な値で定義しておき、update関数もとりあえずモデルをそのまま返すような定義にしておきます。

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

```elm
view : Model -> Html Msg
view model =
  makeList model.list
```

view関数はユーザー定義関数のmakeListを呼び出すだけにしています。
タグの書き出しはmakeListに全部任せる形にしました。

## ユーザー定義関数

### makeList関数

```elm
makeList : List String -> Html Msg
makeList list =
  ul [] ( List.map makeListItem list )
```

ulタグを書き出す関数です。
中ではList.map関数を使ってlistの各要素にmakeListItemを適用した結果をulタグの中身に設定しています。
つまりリストアイテムを生成して設定しています。

### makeListItem関数

```elm
makeListItem : String -> Html Msg
makeListItem item =
  li [] [ text item ]
```

liタグを書き出す関数です。
与えられた文字列をliタグの中に出力しています。

# まとめ

今回のプログラムではinit関数で初期化したモデル使ってview関数がページを描画するだけの処理になっています。
単純にHTMLタグを出力するだけなのでBrowser.sandboxを使う必要はないんですが、次から必要になってくるので今回から利用する形で実装してみました。

次はC(Create)を実装します。

[ElmでCRUDを作る - 其のC ①](https://qiita.com/akkey2475/items/a256ae33449e06d0d370)

また、この記事であまり深く解説していないinit、update、view関数について少しだけちゃんと解説してみた記事がありますので、もし分かりづらかった方は参考にご覧ください。名前がちょっとふざけてますが真面目に書きました。

[ElmでBrowserモジュールを使って「Hello World!!」する](https://qiita.com/akkey2475/items/7dcb1481b419a80cda66)

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

# おまけ

今回はリストタグを出力するために２つの関数を作って行いましたが、関数なしでもできます。

## 別の実装例１

makeListItem関数だけ使う場合

```elm
view : Model -> Html Msg
view model =
  ul [] ( List.map makeListItem list )
```

## 別の実装例２

ユーザー定義関数を１つも使わない場合

```elm
view : Model -> Html Msg
view model =
  ul [] ( List.map ( \itemText -> li [] [ text itemText ] ) model.list )
```

見ての通り、実際ユーザー定義関数なしでもそこまでごちゃごちゃしないんですが、一個一個の関数が割と単純に見えるようにしてみました。
makeList関数はulタグを出力する、makeListItem関数はliタグを出力する、という感じです。