A list zipper that can also focus on a hole between items.
An empty FocusList on a hole
with nothing before and after it.
It's the loneliest of all FocusLists.
<>import Fillable
FocusList.empty
|> FocusList.toStack
--> Fillable.emptyA FocusList with a single focussed item in it,
nothing before and after it.
<🍊>import Stack
FocusList.only "wat"
|> FocusList.current
--> "wat"
FocusList.only "wat"
|> FocusList.toStack
--> Stack.only "wat"The current focussed item.
🍍 🍓 <🍊> 🍉 🍇 -> 🍊FocusList.only "hi there"
|> FocusList.current
--> "hi there"
FocusList.only 1
|> FocusList.append [ 2, 3, 4 ]
|> FocusList.last
|> FocusList.current
--> 4The items before the location of the focus.
🍍 🍓) <🍊> 🍉 🍇import Fillable exposing (Empty, filled)
import Stack exposing (StackFilled, topAndBelow)
FocusList.only 0
|> FocusList.append [ 1, 2, 3 ]
|> FocusList.next
|> Fillable.andThen FocusList.next
|> Fillable.map FocusList.before
--> filled (topAndBelow 0 [ 1 ])
--: Empty Possibly (Empty Possibly (StackFilled number_))The items after the location of the focus.
🍍 🍓 <🍊> (🍉 🍇import Fillable exposing (Empty, filled)
import Stack exposing (StackFilled, topAndBelow)
FocusList.only 0
|> FocusList.append [ 1, 2, 3 ]
|> FocusList.next
|> Fillable.map FocusList.after
--> filled (topAndBelow 2 [ 3 ])
--: Empty Possibly (Empty Possibly (StackFilled number_))Move the focus to the next item, if there is one.
<🍊> 🍉 🍇 -> 🍊 <🍉> 🍇import Fillable exposing (filled)
FocusList.only 0
|> FocusList.append [ 1, 2, 3 ]
|> FocusList.next
|> Fillable.map FocusList.current
--> filled 1This also works from within holes:
🍊 <> 🍉 🍇 -> 🍊 <🍉> 🍇import Fillable exposing (Empty, filled)
FocusList.empty
|> FocusList.insertAfter "foo"
|> FocusList.next
--> filled (FocusList.only "foo")
--: Empty Possibly (ListFocusingHole Never String)If there is no next item, the result is empty.
import Fillable
FocusList.empty
|> FocusList.next
--> Fillable.empty
FocusList.only 0
|> FocusList.append [ 1, 2, 3 ]
|> FocusList.last
|> FocusList.next
--> Fillable.emptyMove the focus to the previous item, if there is one.
🍊 <🍉> 🍇 -> <🍊> 🍉 🍇import Fillable exposing (Empty, filled)
FocusList.empty |> FocusList.previous
--> Fillable.empty
FocusList.only "hello"
|> FocusList.append [ "holey", "world" ]
|> FocusList.last
|> FocusList.previous
|> Fillable.map FocusList.current
--> filled "holey"
--: Empty Possibly (ListFocusingHole Never String)This also works from within holes:
🍊 🍉 <> 🍇 -> 🍊 <🍉> 🍇import Fillable exposing (Empty, filled)
FocusList.empty
|> FocusList.insertBefore "foo"
|> FocusList.previous
--> filled (FocusList.only "foo")
--: Empty Possibly (ListFocusingHole Never String)Move the focus to the hole right after the currently focussed location. A hole is a whole lot of nothingness, so it's always there.
🍍 <🍊> 🍉 -> 🍍 🍊 <> 🍉import Stack exposing (topAndBelow)
FocusList.only "hello"
|> FocusList.append [ "world" ]
|> FocusList.nextHole
|> FocusList.plug "holey"
|> FocusList.toStack
--> topAndBelow "hello" [ "holey", "world" ]Move the focus to the hole right before the currently focussed location.
Feel free to plug that hole right up!
🍍 <🍊> 🍉 -> 🍍 <> 🍊 🍉import Stack exposing (topAndBelow)
FocusList.only "world"
|> FocusList.previousHole
|> FocusList.plug "hello"
|> FocusList.toStack
--> topAndBelow "hello" [ "world" ]Focus the first item.
🍍 🍓 <🍊> 🍉 -> <🍍> 🍓 🍊 🍉FocusList.only 1
|> FocusList.append [ 2, 3, 4 ]
|> FocusList.prepend [ 4, 3, 2 ]
|> FocusList.first
|> FocusList.current
--> 4Focus the last item.
🍓 <🍊> 🍉 🍇 -> 🍓 🍊 🍉 <🍇>import Stack exposing (topAndBelow)
FocusList.only 1
|> FocusList.append [ 2, 3, 4 ]
|> FocusList.last
|> FocusList.current
--> 4
FocusList.only 1
|> FocusList.append [ 2, 3, 4 ]
|> FocusList.last
|> FocusList.before
--> topAndBelow 1 [ 2, 3 ]
--: Empty Possibly (StackFilled number_)Focus the hole before the first item. Remember that holes surround everything!
🍍 🍓 <🍊> 🍉 -> <> 🍍 🍓 🍊 🍉import Stack exposing (topAndBelow)
FocusList.only 1 -- <1>
|> FocusList.append [ 3, 4 ] -- <1> 3 4
|> FocusList.nextHole -- 1 <> 3 4
|> FocusList.plug 2 -- 1 <2> 3 4
|> FocusList.beforeFirst -- <> 1 2 3 4
|> FocusList.plug 0 -- <0> 1 2 3 4
|> FocusList.toStack
--> topAndBelow 0 [ 1, 2, 3, 4 ]Focus the hole after the end. Into the nothingness.
🍓 <🍊> 🍉 -> 🍓 🍊 🍉 <>import Stack exposing (topAndBelow)
FocusList.only 1 -- <1>
|> FocusList.append [ 2, 3 ] -- <1> 2 3
|> FocusList.afterLast -- 1 2 3 <>
|> FocusList.plug 4 -- 1 2 3 <4>
|> FocusList.toStack
--> topAndBelow 1 [ 2, 3, 4 ]Find the first item in the FocusList the matches a predicate,
returning a FocusList focussed on that item if it was found.
This start from the current focussed location and searches towards the end.
import Fillable exposing (filled)
FocusList.only 4
|> FocusList.append [ 2, -1, 0, 3 ]
|> FocusList.findForward (\item -> item < 0)
|> Fillable.map FocusList.current
--> filled -1
FocusList.only -4
|> FocusList.append [ 2, -1, 0, 3 ]
|> FocusList.findForward (\item -> item < 0)
|> Fillable.map FocusList.current
--> filled -4Find the first item matching a predicate, moving backwards from the current position.
import Fillable exposing (filled)
FocusList.only 4
|> FocusList.prepend [ 2, -1, 0, 3 ]
|> FocusList.findBackward (\item -> item < 0)
|> Fillable.map FocusList.current
--> filled -1Put a stack of items to the end after anything else.
🍒🍋
🍓 <🍊> 🍉 🍇 ↓/import Stack exposing (topAndBelow)
FocusList.only 123
|> FocusList.append [ 456 ]
|> FocusList.append [ 789, 0 ]
|> FocusList.toStack
--> topAndBelow 123 [ 456, 789, 0 ]Put items to the end after anything else.
🍒🍋
🍓 <🍊> 🍉 🍇 ↓/import Stack exposing (topAndBelow)
FocusList.only 123
|> FocusList.append [ 456 ]
|> FocusList.append [ 789, 0 ]
|> FocusList.toStack
--> topAndBelow 123 [ 456, 789, 0 ]Put a stack of items to the beginning before anything else.
🍒🍋
\↓ 🍍 🍓 <🍊> 🍉import Stack exposing (topAndBelow)
FocusList.only 1
|> FocusList.append [ 2, 3, 4 ]
|> FocusList.last
|> FocusList.prependStack (topAndBelow 5 [ 6, 7 ])
|> FocusList.toStack
--> topAndBelow 5 [ 6, 7, 1, 2, 3, 4 ]Put items to the beginning before anything else.
🍒🍋
\↓ 🍍 🍓 <🍊> 🍉import Stack exposing (topAndBelow)
FocusList.only 1
|> FocusList.append [ 2, 3, 4 ]
|> FocusList.last
|> FocusList.prepend [ 5, 6, 7 ]
|> FocusList.toStack
--> topAndBelow 5 [ 6, 7, 1, 2, 3, 4 ]If an item is focussed, alter it based on its current value.
import Stack exposing (topAndBelow)
FocusList.only "first"
|> FocusList.prepend [ "zeroth" ]
|> FocusList.append [ "second", "third" ]
|> FocusList.alterCurrent String.toUpper
|> FocusList.toStack
--> topAndBelow "zeroth" [ "FIRST", "second", "third" ]Fill in or replace the focussed thing in the FocusList.
🍓 <?> 🍉 -> 🍓 <🍒> 🍉import Stack exposing (topAndBelow)
FocusList.empty
|> FocusList.insertBefore "🍓" -- "🍓" <>
|> FocusList.insertAfter "🍉" -- "🍓" <> "🍉"
|> FocusList.plug "🍒" -- "🍓" <"🍒"> "🍉"
|> FocusList.toStack
--> topAndBelow "🍓" [ "🍒", "🍉" ]Punch a hole by removing the focussed thing.
🍓 <?> 🍉 -> 🍓 <> 🍉import Fillable exposing (filled)
FocusList.only "hello"
|> FocusList.append [ "holey", "world" ]
|> FocusList.next
|> Fillable.map FocusList.remove
|> Fillable.map FocusList.toList
--> filled [ "hello", "world" ]Apply a function to all items coming before the current focussed location.
import Stack exposing (topAndBelow)
FocusList.only "second"
|> FocusList.prepend [ "zeroth", "first" ]
|> FocusList.alterBefore String.toUpper
|> FocusList.toStack
--> topAndBelow "ZEROTH" [ "FIRST", "second" ]Apply a function to all items coming after the current focussed location.
import Stack exposing (topAndBelow)
FocusList.only "zeroth"
|> FocusList.append [ "first", "second" ]
|> FocusList.alterAfter String.toUpper
|> FocusList.toStack
--> topAndBelow "zeroth" [ "FIRST", "SECOND" ]Insert an item after the focussed location.
🍒
🍓 <🍊> ↓ 🍉 🍇import Stack exposing (topAndBelow)
FocusList.only 123
|> FocusList.append [ 789 ]
|> FocusList.insertAfter 456
|> FocusList.toStack
--> topAndBelow 123 [ 456, 789 ]Insert multiple items using squeezeInAfter.
Insert an item before the focussed location.
🍒
🍍 🍓 ↓ <🍊> 🍉import Stack exposing (topAndBelow)
FocusList.only 123
|> FocusList.insertBefore 456
|> FocusList.toStack
--> topAndBelow 456 [ 123 ]Insert multiple items using squeezeInBefore.
Prepend a Stack of items directly before the focussed location.
🍒🍋
🍍 🍓 \↓/ <🍊> 🍉import Stack exposing (topAndBelow)
FocusList.only 0
|> FocusList.squeezeStackInBefore
(topAndBelow -5 [ -4 ])
|> FocusList.squeezeStackInBefore
(topAndBelow -3 [ -2, -1 ])
|> FocusList.toStack
--> topAndBelow -5 [ -4, -3, -2, -1, 0 ]Prepend items directly before the focussed location.
🍒🍋
🍍 🍓 \↓/ <🍊> 🍉import Stack exposing (topAndBelow)
FocusList.only 0
|> FocusList.squeezeInBefore [ -5, -4 ]
|> FocusList.squeezeInBefore [ -3, -2, -1 ]
|> FocusList.toStack
--> topAndBelow -5 [ -4, -3, -2, -1, 0 ]Append a Stack of items directly after the focussed location.
🍒🍋
🍓 <🍊> \↓/ 🍉 🍇import Stack exposing (topAndBelow)
FocusList.only 0
|> FocusList.squeezeStackInAfter
(topAndBelow 4 [ 5 ])
|> FocusList.squeezeStackInAfter
(topAndBelow 1 [ 2, 3 ])
|> FocusList.toStack
--> topAndBelow 0 [ 1, 2, 3, 4, 5 ]Append items directly after the focussed location.
🍒🍋
🍓 <🍊> \↓/ 🍉 🍇import Stack exposing (topAndBelow)
FocusList.only 0
|> FocusList.squeezeInAfter [ 4, 5 ]
|> FocusList.squeezeInAfter [ 1, 2, 3 ]
|> FocusList.toStack
--> topAndBelow 0 [ 1, 2, 3, 4, 5 ]Change every item based on its current value.
import Stack exposing (topAndBelow)
FocusList.only "first"
|> FocusList.prepend [ "zeroth" ]
|> FocusList.append [ "second", "third" ]
|> FocusList.map String.toUpper
|> FocusList.toStack
--> topAndBelow "ZEROTH" [ "FIRST", "SECOND", "THIRD" ]Apply multiple different functions on the parts of a FocusList- what
comes before, what comes after, and the current item if there is one.
import Stack exposing (topAndBelow)
FocusList.only "first"
|> FocusList.append [ "second" ]
|> FocusList.nextHole
|> FocusList.plug "one-and-a-halfth"
|> FocusList.mapParts
{ before = \item -> "before: " ++ item
, current = \item -> "current: " ++ item
, after = \item -> "after: " ++ item
}
|> FocusList.toStack
--> topAndBelow
--> "before: first"
--> [ "current: one-and-a-halfth"
--> , "after: second"
--> ]Flattens the FocusList into a Stack:
import Fillable
import Stack exposing (topAndBelow)
FocusList.empty
|> FocusList.toStack
--> Fillable.empty
FocusList.only 123
|> FocusList.append [ 789 ]
|> FocusList.nextHole
|> FocusList.plug 456
|> FocusList.toStack
--> topAndBelow 123 [ 456, 789 ]the type information gets carried over, so
Item -> Stack.Never
PossiblyConverts it to a flattened list:
FocusList.only 456
|> FocusList.prepend [ 123 ]
|> FocusList.append [ 789 ]
|> FocusList.toList
--> [ 123, 456, 789 ]Only use this if you need a list in the end.
Otherwise, use toStack to preserve some information about its length.
Fillable.empty if the current focussed thing is a hole,
Fillable.filled if it is an item.
import Fillable
FocusList.only 3
|> FocusList.append [ 2, 1 ]
|> FocusList.nextHole
|> FocusList.focusingItem
--> Fillable.emptyChange the possiblyOrNever type.
A ListFocusingHole possiblyOrNever
can't be used as a ListFocusingHole Possibly?
import Possibly exposing (Possible)
FocusList.adaptType (always Possible)A ListFocusingHole Never
can't be unified with ListFocusingHole Possibly or possiblyOrNever?
FocusList.adaptType neverPlease read more at Fillable.adaptType.
A special kind of list with elements of type
item.The focus can be
🍍 🍓 <🍊> 🍉 🍇:ListFocusingHole Never🍍 🍓 <?> 🍉 🍇:ListFocusingHolePossibly<?>means both are possible:🍍 🍓 <> 🍉 🍇: a hole between items ... Heh.🍍 🍓 <🍊> 🍉 🍇in arguments
in types
where
stops the compiler from creating a positional constructor function for
Model.