Help us understand the problem. What is going on with this article?

[Elm]一覧のViewを自在に操る miyamoen/select-list

More than 1 year has passed since last update.

ヤギの人の一覧のViewを自在に操る elm-referenceを読んできてね

概要

  • list viewでindexベースで要素を更新するのは煩雑
  • Mutable なプログラミング言語の「参照」があれば解決する
  • elm-referenceはthis(現在注目している値)とroot(大元の値)の概念を用いて値に注目しつつ元の値を復元することで解決する
  • 今回提案するselect-listでも値に注目しつつ、大元の値(Listに限定)を復元することで解決する

ということで 🎉🎉🎉I have just published miyamoen/select-list!🎉🎉🎉

モチベーション

immutable data structureでtreeをいい感じに更新するZipperっていうものがあります
このselect-listはzipperのlist版です。

elm-referenceの差別化点としてはList特化なのでその分Listには使いやすい感じになってます(当者比

もちろん自分でも普段使いしてます。べんり(当者比

select-listの基本操作

まずは型

type SelectList a
    = SelectList (List a) a (List a)

2個目のaの値が選択されている値(selected value)で、最初のList aが選択値の前のList(list before)、3個目のList aが選択値の後ろのList(list after)です

[ 1, 2, 3, 4, 5, 6, 7 ]

このリストを3を選択したSelectListに変換すると

([] :: 1 :: 2) 3 (4 :: 5 :: 6 :: 7 :: [])

こんな感じになります。beforeは内部的にひっくり返ってるのでひっくり返して表示してます

これのフォーカスを右(after)に2個動かすと

([] :: 1 :: 2 :: 3 :: 4) 5 (6 :: 7 :: [])

こんな感じになります。before/afterなlistの先頭をはいだり足したりしながら手繰り寄せる感じですね。内部の話なんで本題ではないんですがこんな仕組みになってます

select-listをつかって書き直してみる

一覧のViewを自在に操る elm-referenceは読みましたか?読みましたよね?いきなり例出しますよ?

type Msg
    = ClickNumber (SelectList Int)


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ClickNumber selectList ->
            ( { model
                | nums =
                    SelectList.toList <|
                        SelectList.updateSelected ((+) 1) selectList
              }
            , Cmd.none
            )


view : Model -> Html Msg
view model =
    div [] <| SelectList.selectedMapForList renderRow model.nums


renderRow : SelectList Int -> Html Msg
renderRow selected =
    div
        [ Events.onClick (ClickNumber selected) ]
        [ text <| String.fromInt <| SelectList.selected selected ]

elm-referenceとほぼ一緒です。Msgに渡すものがReference Int (List Int)からSelectList Intに代わったくらいです

そして一番大事なSelectList.selectedMapForListの型ですが

selectedMapForList : (SelectList a -> b) -> List a -> List b

比べてみましょう

selectedMapForList : (SelectList a   -> b) ->            List a    -> List b
unwrap :             (Reference  a x -> b) -> Reference (List a) x -> List b
indexedMap :         (Int ->     a   -> b) ->            List a    -> List b

indexedMapと比較するとindexの代わりにSelectList aを渡しています
aの値は渡していませんがSelectListが選択している値がaということになります

また、型構造を上で見た通り全体の構造が分かるのでindexも取れます。まあふいんきでわかってもらえたと思うのであとはpackage document読んでください(型眺めてるほうがわかることない?)

もっと比較したい場合は…

ここからふいんき度上がります。

elm-referenceのほうがいい点

  • Reference (List a) xのxで大本の構造まで一発で戻せそう
    • select-listではlistまでしか戻せないので
  • list以外にも使える抽象

select-listのほうがいい点

  • List特化
    • indexとか他の要素へもアクセスできる
    • 選択している要素を上下に動かすとか要素の挿入とか削除とかのAPIを用意している
      • elm-referenceexampleで上下移動と削除の例があるんですがちょっとわたしには実装が難しすぎました

結局自分で使うのにちょうどいいのを追求していく感じで作ってます

宣伝

Elm-jpでは公式ガイドの翻訳活動をしています

深刻なレビュアー不足なので助けて

miyamo_madoka
わたしの発言は一くろすすてっちゃ的発言であってー、ぷろぐらみんぐとかえすあいあーとかー所属企業とかー関係なくてーとりあえず何か作りたいなあっていつも思ってますー
elm-jp
主に日本で活動する Elm 利用者のコミュニティです。
https://elm-lang.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした