追記
この記事は古いです。過去のものです。忘れましょう
#対象読者
Elmを勉強しようと思って公式のドキュメント読んででelm-architecture-tutorialを見てどういう仕組みだよこれってなった人(つまり私)
コードとかは上記チュートリアルとライブラリからの引用。内容としてはライブラリのコードを追っかけて理解できたことをまとめている。javascriptまでは踏み込んでない
こんなバージョン。0.15.1
"dependencies": {
"elm-lang/core": "2.1.0 <= v < 3.0.0",
"evancz/start-app": "2.0.1 <= v < 3.0.0"
},
"elm-version": "0.15.1 <= v < 0.16.0"
#全体を見る
import Html exposing (div, button, text)
import Html.Events exposing (onClick)
import StartApp.Simple as StartApp
main =
StartApp.start { model = model, view = view, update = update }
model = 0
view address model =
div []
[ button [ onClick address Decrement ] [ text "-" ]
, div [] [ text (toString model) ]
, button [ onClick address Increment ] [ text "+" ]
]
type Action = Increment | Decrement
update action model =
case action of
Increment -> model + 1
Decrement -> model - 1
modelとviewとupdateを用意してStartApp.Simple.startにかませればあとはよしなにやってくれるらしい……
#Addressを理解する
上記view関数の引数にaddressが登場してます。チュートリアルをみるとviewの型はview : Signal.Address Action -> Model -> Html
で引数address
の型はSignal.Address Action
です。
このAddress
型はSignal.elmで定義されています
type alias Mailbox a =
{ address : Address a
, signal : Signal a
}
type Address a =
Address (a -> Task () ())
Address
型はMailbox
型とセットです。Mailbox
は関数Signal.mailbox : a -> Mailbox a
で作ります。中にはaddress
とsignal
が入っています。
この中のaddress
に向かってMessage(a型の値)を送るとsignal
が更新されます。
view
関数で使われているaddress
の正体はこの型です。型はAddress Action
なのでStartApp.Simple.start
の中では、Mailbox Action
型の値があってそこからSignal Action
を取り出して使っているんでしょう。(実際は少し違います)
#StartApp.Simple
の実装
短くてsimpleです
type alias Config model action =
{ model : model
, view : Address action -> model -> Html
, update : action -> model -> model
}
start : Config model action -> Signal Html
start config =
let
actions =
Signal.mailbox Nothing
address =
Signal.forwardTo actions.address Just
model =
Signal.foldp
(\(Just action) model -> config.update action model)
config.model
actions.signal
in
Signal.map (config.view address) model
Config
型が引数として渡している{ model = model, view = view, update = update }
の型です。start
関数はAction
のmailbox
を作ってそこからAction
を取り出してSignal Model
を作りview
関数にmapしてます。
##forwardTo
そしてチュートリアルの2にもあるSignal.forwardTo
関数を使ってます。mailbox
の型は正確にはMailbox Maybe a
です。address
にはAction
を送るのでそのままAction
が送れる型にaddress
を変えておく必要があります。
forwardTo : Address b -> (a -> b) -> Address a
forwardTo (Address send) f =
Address (\x -> send (f x))
(a -> b)を使って渡されたaの型を変換しています。Signal.forwardTo actions.address Just
ではjust
が使われています。
どうやらJust Decrement
でMaybe Action
型となるのでJust
はa -> Maybe a
型になるようです。
forwardTo
でできたaddress
にAction
を送ることでmailbox
が更新されるようになりました。
実際にaddress
にAction
を送っているのはonClick
関数などです。
#最後に
こうしてみるとStartApp.Simple
はMailBox
を中心とした薄めのラッパーという感じがします。ちょっとした仕組みでフレームワークみたいなものを実現していて驚きました。
Elmは日本語情報少ないので困りましたが結局コード読んでたら何とかわかりました。
せっかくなのでまとめてみました。学習の手助けになれば幸いです。