Elmの良いところってそこそこ高度な動きをするものをすぐ作れるところだと思います。
モチベーション上がるし関数型を学ぶには良い教材のような気がします。慣れるまでは大変でしたが、今は書いててとても楽しいです。
勉強のために作ったサンプルコードがもうちょいあるのであと何記事分か書いてみる予定です。
続きの記事も書きました。
ElmでCRUDを作る - 其のR (この記事)
今回作ったもの
TODOリストです。
すでにたくさんサンプルコード有るわ!って感じですが、同じTODOリストでも違う実装のサンプルコードはいくらあっても良いものです。(と思う)
最初はリストを表示するだけのもの(Read)から、リストの追加(Create)、リストの削除(Delete)と段階を追って実装していきます。
ちなみに実は編集機能のU(Update)はまだ自分には難しくて作れてないので今回実装はありません。ごめんなさい。
この記事ではCRUDのR(Read)をまず実装しようと思います。
モデルのリストをリストタグで表示するだけです。
完成品
とりあえず、完成品こちらです。ここ(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 ]
解説
モジュールの読み込み
import Browser
import Html exposing (..)
モジュールはBrowserとHtmlを使います。
メイン関数
main =
Browser.sandbox
{ init = init
, update = update
, view = view
}
今回はBrowser.sandboxを使用します。
モデルの定義と初期化
type alias Model =
{ list : List String }
init : Model
init = Model ["item1", "item2", "item3"]
モデルはList String型のlistという要素を一つ持つレコードとして定義します。
初期値には、とりあえず3つの要素を持つリストを指定してみました。
更新処理の定義
type Msg = None
update : Msg -> Model -> Model
update msg model = model
更新処理は今回使わないので、Msgには適当な値で定義しておき、update関数もとりあえずモデルをそのまま返すような定義にしておきます。
ページ描画処理の定義
view : Model -> Html Msg
view model =
makeList model.list
view関数はユーザー定義関数のmakeListを呼び出すだけにしています。
タグの書き出しはmakeListに全部任せる形にしました。
ユーザー定義関数
makeList関数
makeList : List String -> Html Msg
makeList list =
ul [] ( List.map makeListItem list )
ulタグを書き出す関数です。
中ではList.map関数を使ってlistの各要素にmakeListItemを適用した結果をulタグの中身に設定しています。
つまりリストアイテムを生成して設定しています。
makeListItem関数
makeListItem : String -> Html Msg
makeListItem item =
li [] [ text item ]
liタグを書き出す関数です。
与えられた文字列をliタグの中に出力しています。
まとめ
今回のプログラムではinit関数で初期化したモデル使ってview関数がページを描画するだけの処理になっています。
単純にHTMLタグを出力するだけなのでBrowser.sandboxを使う必要はないんですが、次から必要になってくるので今回から利用する形で実装してみました。
次はC(Create)を実装します。
また、この記事であまり深く解説していないinit、update、view関数について少しだけちゃんと解説してみた記事がありますので、もし分かりづらかった方は参考にご覧ください。名前がちょっとふざけてますが真面目に書きました。
ElmでBrowserモジュールを使って「Hello World!!」する
ElmでBrowserモジュールを使って「Hello World」をシャウトする
おまけ
今回はリストタグを出力するために2つの関数を作って行いましたが、関数なしでもできます。
別の実装例1
makeListItem関数だけ使う場合
view : Model -> Html Msg
view model =
ul [] ( List.map makeListItem list )
別の実装例2
ユーザー定義関数を1つも使わない場合
view : Model -> Html Msg
view model =
ul [] ( List.map ( \itemText -> li [] [ text itemText ] ) model.list )
見ての通り、実際ユーザー定義関数なしでもそこまでごちゃごちゃしないんですが、一個一個の関数が割と単純に見えるようにしてみました。
makeList関数はulタグを出力する、makeListItem関数はliタグを出力する、という感じです。