Fringe81株式会社アドベントカレンダーの6日目です。
PortをTaskで定義できたら便利だと思って調べたらプロポーザル用に作られたレポジトリがあったため紹介。
elm-task-port-example/Main.elm at master · eirslett/elm-task-port-example · GitHub
今回関心ある部分を抜き出してみる。
port getUser : UserQuery -> Task UserError User
type Msg = LoadUser | UserResult (Result UserError User)
getUserTask : Task UserError User
getUserTask = getUser { sessionId = "123", userId = 456 }
update msg model =
case msg of
LoadUser ->
(model, Task.attempt UserResult <| getUser { sessionId = "123", userId = 456 })
UserResult (Ok user) ->
({ model | currentUser = Just user, error = Nothing }, Cmd.none)
UserResult (Err error) ->
({ model | currentUser = Nothing, error = Just error }, Cmd.none)
PortをCmdにするのではなくTaskにする
そうするとTask.attemptでMsgに結果をペイロードとするCmdを発行でき、updateで受け取りそのままcaseでパターンマッチしてコールバックを実行できる
コンパイルはもちろんエラーになるのだけど、これできるようになると便利だなと思った。
(ちなみに、過去にはPortはTaskで定義できたようなので、意図的にできないようにした背景があるのかもしれない)
$ npx elm-make Main.elm --output Main.js
-- PORT ERROR --------------------------------------------------------- Main.elm
Port `getUser` has an invalid type.
19| port getUser : UserQuery -> Task UserError User
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You are saying it should be:
Main.UserQuery -> Task.Task Main.UserError Main.User
But you need to use the particular format described here:
<http://guide.elm-lang.org/interop/javascript.html#ports>
Detected errors in 1 module.
古いversionのPortの仕様について書かれた記事を紹介しておく。
以上。