前回: Elm 0.18 入門(4) 時刻の取得とMaybe
前回はアプリケーション初期化時の現在時刻の取得を実装しました。
今回は現在時刻を毎秒自動更新するようにしてみましょう。
そもそも subscriptions とは
subscriptions
は「予約」「購読」などの意味で、イベントに応じて自動的にアクションを発火するための仕組みです。
今回紹介する一定時間ごとのイベントの他にも(ボタン押下でないような)マウスクリックイベントやキーボード、WebSocketのリクエストなど様々なものがイベントとして指定できます。
また、 subscriptions
関数の入力値として model
を指定することから推測できるように、モデルの状態に応じて反応を変化させることもできます。
subscriptions の実装
まずは subscriptions
関数を次のように更新します。
subscriptions : Model -> Sub Msg
subscriptions model =
- Sub.none
+ let
+ updateCurrentDate t =
+ Date.fromTime t |> UpdateDatetime
+ in
+ Time.every Time.second updateCurrentDate
初めて Time
モジュールを使うので import
を追加します。
import Time exposing (Time)
in
の中から順に関数シグネチャを確認しましょう。
Time.every : Time -> (Time -> msg) -> Sub msg
Time.second : Time
Time.every
は第一引数にインターバル時間を受け取り、そのインターバルで第二引数の関数を呼び出して、アクション(msg
)を生成する Sub msg
を出力します。
Time
型は実際は Float
型なので、例えば5秒ごとに処理をする subscriptions
が作りたい場合は Time.every (5 * Time.second) ...
とすれば良いです。
よりDSLっぽく書きたければ、 import Time exposing (Time, every, second)
として every (5 * second) ...
のように書いてもいいでしょう。
UpdateDatetime : Date -> Msg
Date.fromTime : Time -> Date
呼び出す関数には既に実装している時刻更新用のアクションを作る関数(コンストラクタ)を組み合わせます。ただ、こちらの関数は Date
型を引数にとるので、 Date.fromTime
関数で Time
型の値を変換する必要があります。
|>
に関しては前回の記事を参考にして下さい。
さて、時刻表示が時計のように動いているでしょうか?
ココまでのコード : https://ellie-app.com/cDXLnLdsRa1/2
関数合成
さきほどの記述では、 let ... in ...
を使って呼び出す関数部分をわざわざ定義していましたが、実際には必要ありません。 Time -> Date
と Date -> Msg
を組み合わせて Time -> Msg
の関数を作ればよいのです。これを関数合成と言います。
正にそのようなシグネチャを持つ中置演算子 >>
があります。
(>>) : (a -> b) -> (b -> c) -> a -> c
関数合成を利用することで仮引数 t
を用いた関数定義をしなくても、複数の関数そのものを合成して新しい関数を生成できるのでコードがスッキリします。
subscriptions : Model -> Sub Msg
subscriptions model =
- let
- updateCurrentDate t =
- Date.fromTime t |> UpdateDatetime
- in
- Time.every Time.second updateCurrentDate
+ Time.every Time.second (Date.fromTime >> UpdateDatetime)
ただ、一般には関数合成というと逆の順番で合成をすることが多いです。
f : a -> b
g : b -> c
(<<) : (b -> c) -> (a -> b) -> a -> c
h = g << f
これは、通常の関数適用で考えると g (f x)
となることから、 g << f
(Haskellだと g . f
)という並び方が自然になるためです。
読みやすい方を選んで使うようにしましょう。
ココまでのコード : https://ellie-app.com/cDXLnLdsRa1/3
まとめ
まずはシンプルな subscriptions
の実装をしてみました。
次回は何を作ろうか決めてないですが、アプリケーションっぽいものを作れたらなと思います。