この記事を書いた直後の 5/10 に Elm 0.17 がリリースされ Signal
や Effects
などはなくなってしまいました!
ゴールデンウィークは Elm について調べ、ちょっとしたコードを書いてみました。独特の用語が多くて混乱したので、他の言語の似た概念に当てはめてみます。
これだけ読んでもわからないと思うので、詳しい内容は以下のドキュメントを参照してください。これらを読んでいて混乱してきたら見てもらうとちょうど良いと思います。
Signal まわり
最近 Angular がらみで RxJS を使うようになったので、Rx 用語と対応させてみます。
-
Signal
:Observable
。データがどんどんやってくる出口。 -
Address
:Observer
。データをどんどん投げ込める入り口。 -
Mailbox
:Subject
。上 2 つのセット。Address
に投げ込んだものがSignal
から出てきます。
main
の型は Signal Html
となっており、Elm アプリは変わりゆく Html
をどんどん描画してゆくものだとわかります。
Effects まわり
似た概念が多く、最初混乱しました。
-
Result x a
: Haskell のEither
。失敗する可能性のある処理の「結果」(成功か失敗かはパターンマッチするとわかります) -
Task x a
: JavaScript のPromise
。失敗する可能性のある非同期処理。 -
Effects a
: 抽象化されたTask
。なにもしない、一つのTask
、複数のTask
を表せる。型を見るとわかる通り、成功しようがエラーだろうが結果の型は同じです。通常Task
をもろもろ実行してから、最終的にAction
を返してupdate
へ戻すという形で使われます。 -
port
: JavaScript 側との出入り口。型はSignal a
。実装を指定すると Elm -> JavaScript、しないと JavaScript -> Elm。
関数適用・合成関連
最初はギョッとしましたが、矢印の順番に関数が適用されていくので慣れてみるとわかりやすいですね。
-
<| : (a -> b) -> a -> b
: Haskell の$
。 -
|> : a -> (a -> b) -> b
:<|
の逆。オブジェクト志向っぽく書ける。Elixir や EcmaScript Stage 0 のパイプ演算子。 -
<< : (b -> c) -> (a -> b) -> a -> c
: Haskell の.
。 -
>> : (a -> b) -> (b -> c) -> a -> c
:>>
と逆の関数合成。
感想
- The Elm Architecture に従って子から親を参照しないようにすると、モジュールをまたぐ
Action
を出しにくいなーと思いました。Action
はグローバルに定義しちゃってどこからでも呼べるようにするのがいいのかな? - ボイラープレートを書かないで済ます方法を知りたいです。
- 文法は Haskell っぽいけど、正格評価だし、モナドを使ってどうこうもないし、型クラスもないしで Haskell でフロントエンドを書いて楽しめる、というわけではないなと思いました。