7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-10-15

ヤギの人の一覧の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では公式ガイドの翻訳活動をしています

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

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?