miyamoen/select-list/1.2.0

NOTE: this package is not compatible with Elm 0.19.1

SelectList

Yet another SelectList implementation

A SelectList is a non-empty list which always has exactly one element selected. It is an example of a list zipper.

Inspired by these modules

mapBy is the main function in this package. Use mapBy in view.

view : SelectList String -> Html Msg
view selectList =
    ul [] <|
        SelectList.mapBy
            (\position item ->
                li [ onClick (Set item) ]
                    [ text <| toString <| SelectList.index item
                    , toString <| SelectList.selected item
                    ]
            )
            selectList

Type

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

A nonempty list which always has exactly one element selected.

Create one using fromLists, fromList or singleton.

fromLists : List a -> a -> List a -> SelectList a

A SelectList.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> selected
    == 4
fromList : List a -> Maybe (SelectList a)

A SelectList if list has elements.

If empty, Nothing.

fromList [] == Nothing
fromList [2, 3, 4] == Just (fromLists [] 2 [ 3, 4 ])
singleton : a -> SelectList a

A SelectList containing exactly one element.

singleton 3 == fromLists [] 3 []

Query

toList : SelectList a -> List a

Return a List containing the elements in a SelectList.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> toList
    == [ 1, 2, 3, 4, 5, 6 ]
selected : SelectList a -> a

Return the selected element.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> selected
    == 4
before : SelectList a -> List a

Return the elements before the selected element.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> before
    == [ 1, 2, 3 ]
after : SelectList a -> List a

Return the elements after the selected element.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> after
    == [ 5, 6 ]
index : SelectList a -> Int

Index of the selected element.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> index
    == 3
isHead : SelectList a -> Bool

Check if the selected element is first element.

fromLists [] 4 [ 5, 6 ]
    |> isHead
    == True
isLast : SelectList a -> Bool

Check if the selected element is last element.

fromLists [ 1, 2, 3 ] 4 []
    |> isLast
    == True
length : SelectList a -> Int

Length of SelectList.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> length
    == 6
afterLength : SelectList a -> Int

Length of the elements after the selected element

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> afterLength
    == 2
beforeLength : SelectList a -> Int

Length of the elements before the selected element

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> beforeLength
    == 3

Operations

(SelectList a -> Maybe (SelectList a))
-> SelectList a
-> SelectList a

Attempt to perform action over selectList and return original SelectList in cases where this action returns Nothing.

attempt f selectList =
    f selectList
        |> Maybe.withDefault selectList
append : List a -> SelectList a -> SelectList a

Add elements to the end of a SelectList.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> append [ 7, 8 ]
    |> toList
    == [ 1, 2, 3, 4, 5, 6, 7, 8 ]
prepend : List a -> SelectList a -> SelectList a

Add elements to the beginning of a SelectList.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> prepend [ 7, 8 ]
    |> toList
    == [ 7, 8, 1, 2, 3, 4, 5, 6 ]
= After
| Before

Direction

modify : (a -> a) -> SelectList a -> SelectList a

Modify the selected element using given function.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> modify (\selected -> 2 * selected)
    == fromLists [ 1, 2, 3 ] 8 [ 5, 6 ]
set : a -> SelectList a -> SelectList a

Replace the selected element with new one.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> set 10
    == fromLists [ 1, 2, 3 ] 10 [ 5, 6 ]
insert : Direction -> a -> SelectList a -> SelectList a

Insert the new selected element, then move the old After/Before.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> insert After 8
    == fromLists [ 1, 2, 3 ] 8 [ 4, 5, 6 ]
delete : Direction -> SelectList a -> Maybe (SelectList a)

Delete the selected element, then select After/Before element.

Returns Nothing if list of After/Before elements is empty.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> delete After
    == Just (fromLists [ 1, 2, 3 ] 5 [ 6 ])


fromLists [ 1, 2, 3 ] 4 []
    |> delete After
    == Nothing

Step

step : Direction -> SelectList a -> Maybe (SelectList a)

A selectList selects a Direction element by a step.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> step After
    == Just (fromLists [ 1, 2, 3, 4 ] 5 [ 6 ])


fromLists [ 1, 2, 3 ] 4 []
    |> step After
    == Nothing
steps : Direction -> Int -> SelectList a -> Maybe (SelectList a)

A selectList selects a Direction element by n steps.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> steps After 2
    == Just (fromLists [ 1, 2, 3, 4, 5 ] 6 [])


fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> steps After 3
    == Nothing
moveToHead : SelectList a -> SelectList a

A selectList selects the first element of a selectList.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> moveToHead
    == fromLists [] 1 [ 2, 3, 4, 5, 6 ]
moveToLast : SelectList a -> SelectList a

A selectList selects the last element of a selectList.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> moveToHead
    == fromLists [] 1 [ 2, 3, 4, 5, 6 ]

Transformations

select : (a -> Bool) -> SelectList a -> Maybe (SelectList a)

Change the selected element to the nearest one which passes a predicate function. Find the list after selected element preferentially.

isEven num =
num % 2 == 0


fromLists [ 1, 2 ] 3 [ 4, 5, 6 ]
|> select isEven
== fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
selectAll : SelectList a -> List (SelectList a)

List of all selectList.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    == [ fromLists [] 1 [ 2, 3, 4, 5, 6 ]
       , fromLists [ 1 ] 2 [ 3, 4, 5, 6 ]
       , fromLists [ 1, 2 ] 3 [ 4, 5, 6 ]
       , fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
       , fromLists [ 1, 2, 3, 4 ] 5 [ 6 ]
       , fromLists [ 1, 2, 3, 4, 5 ] 6 []
       ]
map : (a -> b) -> SelectList a -> SelectList b

Transform each element of the SelectList.

fromLists [ 1, 2, 3 ] 4 [ 5, 6 ]
    |> map (\num -> num * 2)
    == fromLists [ 2, 4, 6 ] 8 [ 10, 12 ]
= BeforeSelected
| Selected
| AfterSelected

Position is used with mapBy.

Position is Selected if the selected element, BeforeSelected if an element before the selected element, and AfterSelected if an element after the selected element.

mapBy : (Position -> SelectList a -> b) -> SelectList a -> List b

Transform each element of the SelectList.

The transform function receives a Position and SelectList which selects a transformed element.

mapBy is the main function in this package. Use mapBy in view.

view : SelectList String -> Html Msg
view selectList =
    ul [] <|
        SelectList.mapBy
            (\position item ->
                li [ onClick (Set item) ]
                    [ text <| toString <| SelectList.index item
                    , toString <| SelectList.selected item
                    ]
            )
            selectList

If you can not use non-empty list, use mapBy_ that receives List instead of SelectList.

mapBy_ : (Position -> SelectList a -> b) -> List a -> List b

This receives List instead of SelectList.