直してみよう。
Elmっちへ
ういっすー!
関数型言語が 全く わからなくて、
つらみが 深いので、
1行ずつ コメント入れていきます。
アプリは 書けたら書くマンです!
1ブロックずつメモしていく
exposing / import
-- main関数をMainモジュールとして公開 -- var app = Elm.Main.init({ node: document.querySelector('main') }) module Main exposing (main) -- Browserモジュールをインポート import Browser -- HtmlモジュールからHtml型, button/div/text型をインポート import Html exposing (Html, button, div, text) -- Html.EventsモジュールからonClick関数をインポート import Html.Events exposing (onClick)
- main関数をElm.Main.initでHTMLに出力するためにexport
- HTMLの描画に使用する
Browser.sandbox
を使うためにインポート - HTMLを構成するbutton, div, textを使用するためにHtml型と関数をインポート
- buttonの要素onClickを使用するためにHtml.Eventsからインポート
至って普通のインポートなので特に難しい所なし
type Model
-- Int型のcountにAliasでModelという型名をつけて定義 type alias Model = { count : Int }
- Int型のcount変数(レコード)にModelという型名をつけて持っている
- 頭文字大文字は型である
- ElmだとModelは状態らしいですね
- こんなイメージ
<?php class Model extends int { int count; }
このコードだとメリットわからないけど
type alias User = {id : Int, name : String}
とかだとメリットある。
構造体的なイメージ
initialModel関数
-- Model型のinitialModelを定義 initialModel : Model -- count=0でセット。型はModel(count :int)で定義 initialModel = { count = 0 }
- initialModel : Model
こいつは型定義 - initialModel = { count = 0 }
こいつが実処理
function initialModel(Model $model)
な感じ
コンストラクタ的なイメージ(実際initで使われている)
Msg型
-- Msg型を定義。配入るのはIncrement / Decrementのみ -- ここで言うIncrement/Decrementは型ではなく値 type Msg = Increment | Decrement
- 真骨頂 Msg型という独自の方を定義
- 入るのはIncrement / Decrementという値(型?)
typescript
でもhoge = int | string
って有ったよね - MsgはElmだとなんか色々受け渡して詰め込んでるらしい
Msg = アクション的なイメージ
update関数
-- update関数 Msg Modelを引数にModelを返す -- function update(Msg msg, Model model): Model 的な -- 省略できる(型推論)けど、書くのが正しい update : Msg -> Model -> Model -- Msg msg, Model model update msg model = -- if (msg === Increment) elseif (msg === Decrement) 的な -- returnはない。そのまま返り値になる(カリー化とか部分適用とか知らん、いらん) -- パターンマッチってやつらしい case msg of -- Incrementの時 Increment -> -- model(count:int)を+1で更新する、レコードなのでこの構文 { model | count = model.count + 1 } -- Decrementの時 Decrement -> -- model(count:int)を-1で更新する、レコードなのでこの構文 { model | count = model.count - 1 }
急に難易度上げるのやめてほしい、初心者殺し
function update(Msg msg, Model model): Model
っぽいけどその実カリー化されているらしい ナマステ- update(Msg msg)を呼ぶとfunction(Model model)が返ってくる(謎)
- x, yの座標処理でxを固定しつつyに対して処理する~とかで活きるかも
- つまりこんなことが出来る
-- numberとnumberを受け取ってnumberを返す add : number -> number -> number add : a b = a + b -- add: a b のaが1に固定された関数が作れた add1 = add 1 -- bを2で呼び出す -- これで3が返ってくる add 2
- パターンマッチは割と見たまんま
渡したMsg msg = Increment | Decrement
を処理する { model | count = model.count +1 }
この書き方はmodelのcountにmodel.countを取り出して+1した値を代入している
レコード取り出すのはこういう記法らしい
view関数
-- view関数 Modelを引数に(Html Msg)のtupleが返る -- function view(Model model): tuple(Html html, Msg msg) 的な view : Model -> Html Msg -- Model model view model = -- (div[]がHtml, [...]がMsg) なのかな… div [] -- 要素 属性 要素の中身 -- div [onclick] [text] みたいな感じ -- なので今回はdiv 要素なし 中身がネストしてbutton [] []という形になっている [ button [ onClick Increment ] [ text "+1" ] , div [] [ text <| String.fromInt model.count ] , button [ onClick Decrement ] [ text "-1" ]
- Modelを引数に受けて(Html Msg)のtupleを返すみたいなイメージ
- div[] button とかがHtml
- onClickの Increment/DecrementがMsgらしい
どういった経路でココに繋がるのかさっぱりわからん
main関数
-- main関数 Program型 フラグなし Model Msg -- function (Program program, Model model, Msg msg): void -- 第2引数はflagでなにもないことを示しているらしい -- https://heimdal.hatenablog.com/entry/elm-0.19-sandbox#sandbox main : Program () Model Msg main = Browser.sandbox { init = initialModel , view = view , update = update }
- initで起動時に動く関数を指定
- viewで描画する関数を指定(恐らくHtml Msgになるんだと思う)
- モデル更新処理で動く関数updateを指定
わからんところ
- update関数はどんな流れでviewのIncrement/Decrementと繋がっているのか
- view関数のMsgはどうIncrement/Decrementと繋がっているのか
まとめ
input outputがよくあるアプリケーションと違うので全くわからん
写経したり動かすぐらいなら出来るけど、ちゃんと理解してないのですぐ詰まる
誰か助けてくれ