alexanderkiel / list-selection / List.Selection

This module exposes a list that has at most one selected item.

The invariants here:

But, these only hold if there are no duplicates in your list.

Converting


type Selection a

A list of items, one of which might be selected.

fromList : List a -> Selection a

Create a Selection a with nothing selected.

toList : Selection a -> List a

Convert a Selection list back to a regular list. This is useful for creating view functions, for example. If you want a list that has the selected item, use mapSelected like this:

[ 1, 2, 3 ]
    |> fromList
    |> select 2
    |> mapSelected
        { selected = (,) True
        , rest = (,) False
        }
    |> toList
    --> [ (False, 1), (True, 2), (False, 3) ]

Selecting

select : a -> Selection a -> Selection a

Mark an item as selected. This will select at most one item. Any previously selected item will be unselected.

fromList ["Burrito", "Chicken Wrap", "Taco Salad"]
    |> select "Burrito"
    |> selected --> Just "Burrito"

Attempting to select an item that doesn't exist is a no-op.

fromList ["Burrito", "Chicken Wrap", "Taco Salad"]
    |> select "Doner Kebab"
    |> selected --> Nothing

selectBy : (a -> Basics.Bool) -> Selection a -> Selection a

Mark an item as selected by specifying a function. This will select the first item for which the function returns True. Any previously selected item will be unselected.

fromList ["Burrito", "Chicken Wrap", "Taco Salad"]
    |> selectBy (String.startsWith "B")
    |> selected --> Just "Burrito"

deselect : Selection a -> Selection a

Deselect any selected item. This is a no-op if nothing is selected in the first place.

selected : Selection a -> Maybe a

Get the selected item, which might not exist.

fromList ["Burrito", "Chicken Wrap", "Taco Salad"]
    |> select "Burrito"
    |> selected --> Just "Burrito"

Transforming

map : (a -> b) -> Selection a -> Selection b

Apply a function to all the items.

fromList [1, 2, 3]
    |> map ((*) 2)
    |> toList --> [2, 4, 6]

mapSelected : { selected : a -> b, rest : a -> b } -> Selection a -> Selection b

Apply a function to all the items, treating the selected item specially.

fromList [1, 2, 3]
    |> select 2
    |> mapSelected { selected = (*) 2, rest = identity }
    |> toList --> [1, 4, 3]

filter : (a -> Basics.Bool) -> Selection a -> Selection a

Filter all items where predicate evaluates to false, preserving selected item when unfiltered.

fromList [1, 2, 3]
    |> select 2
    |> filter ((>) 2)
    |> toList --> [1]