Emptiable.empty to create an Empty Possibly stack
A stack with just 1 single element
import Emptiable
import Stack exposing (onTopLay)
Stack.one ":)"
--> Emptiable.empty |> onTopLay ":)"A stack from a top element and a List of elements below
Stack.topBelow ":)" [ "wait", "a", "moment" ]
--> Stack.topBelow "wait" [ "a", "moment" ]
--> |> onTopLay ":)"Take a tuple ( top, List belowElement )
from another source like turboMaCk/non-empty-list-alias
and convert it to an Emptiable (StackTopBelow top belowElement) never_
Use topBelow if you don't already have a tuple to convert from
Convert a List element to a Empty Possibly (Stacked element).
The Lists head becomes top, its tail is attachd below
import Possibly exposing (Possibly)
import Emptiable
import Stack exposing (topBelow)
[] |> Stack.fromList
--> Emptiable.empty
[ "hello", "emptiness" ] |> Stack.fromList
--> topBelow "hello" [ "emptiness" ]
--: Empty Possibly (Stacked String)When constructing from known elements, always prefer
import Stack exposing (topBelow)
topBelow "hello" [ "emptiness" ]Convert to an Emptiable (Stacked Char) Possibly.
The Strings head becomes top, its tail is attachd below
import Possibly exposing (Possibly)
import Emptiable
import Stack exposing (topBelow)
"" |> Stack.fromString
--> Emptiable.empty
"hello" |> Stack.fromString
--> topBelow 'h' [ 'e', 'l', 'l', 'o' ]
--: Emptiable (Stacked Char) PossiblyWhen constructing from known elements, always prefer
import Stack exposing (topBelow)
onTopLay 'h' ("ello" |> Stack.fromString)Emptiable (Stacked ...) Possibly Fuzzer.
Generates stacks of varying length <= 32
import Stack exposing (topBelow)
import Fuzz
Stack.fuzz (Fuzz.intRange 0 9)
|> Fuzz.examples 3
--> [ topBelow 2 [ 2, 5, 3, 8, 9, 4, 1, 0, 6, 6, 4, 7, 2, 6, 5 ]
--> , topBelow 8 [ 8, 0, 9, 8, 1, 0, 4, 1, 4, 6, 3, 4 ]
--> , topBelow 9 [ 7, 1, 5, 8, 2, 8, 3, 7, 4, 7 ]
--> ]
--: List (Emptiable (Stacked Int) Possibly)Emptiable Stacked Never Fuzzer.
Generates stacks of varying length <= 32
import Stack exposing (topBelow)
import Fuzz
Stack.filledFuzz (Fuzz.intRange 0 9)
|> Fuzz.examples 3
--> [ topBelow 4 [ 2, 2, 5, 3, 8, 9, 4, 1, 0, 6, 6, 4, 7, 2, 6, 5 ]
--> , topBelow 3 [ 4, 4, 5, 1, 7, 4, 2, 5, 6, 9, 7, 0, 1, 4, 1, 3, 2, 9, 6, 9, 0, 8, 3, 3, 3, 1, 5, 4, 9, 5, 2, 8 ]
--> , topBelow 5 [ 4, 9, 8, 9 ]
--> ]The first value
import Stack exposing (top, onTopLay)
Stack.one 3
|> onTopLay 2
|> top
--> 2How many element there are
import Stack exposing (onTopLay)
Stack.one 3
|> onTopLay 2
|> Stack.length
--> 2O(n) like List.length
Add an element to the front
import Emptiable
import Stack exposing (topBelow, onTopLay)
topBelow 2 [ 3 ] |> onTopLay 1
--> topBelow 1 [ 2, 3 ]
Emptiable.empty |> onTopLay 1
--> Stack.one 1Everything after the first element
import Stack exposing (topBelow)
import Linear exposing (Direction(..))
Stack.one 2
|> Stack.onTopLay 3
|> Stack.attach Down (topBelow 1 [ 0 ])
|> Stack.removeTop
--> topBelow 0 [ 3, 2 ]
--: Emptiable (Stacked number_) PossiblyChange the first element based on its current value
import Stack
Stack.topBelow "Helpy IQ 4000 – the amazing vacuum cleaner"
[ "faster and more thorough than ever seen before!" ]
|> Stack.topAlter (\firstLine -> "Introducing: " ++ firstLine)
--> Stack.topBelow "Introducing: Helpy IQ 4000 – the amazing vacuum cleaner" [ "faster and more thorough than ever seen before!" ]Flip the order of the elements
import Stack exposing (topBelow)
topBelow "l" [ "i", "v", "e" ]
|> Stack.reverse
--> topBelow "e" [ "v", "i", "l" ]Keep all filled elements
and drop all empty elements
import Emptiable exposing (filled)
import Stack exposing (topBelow)
topBelow Emptiable.empty [ Emptiable.empty ]
|> Stack.fills
--> Emptiable.empty
topBelow (filled 1) [ Emptiable.empty, filled 3 ]
|> Stack.fills
--> topBelow 1 [ 3 ]As you can see, if only the top is fill a value, the result is non-empty
Glue the elements of a given stack to the end in a given direction of the stack
import Linear exposing (Direction(..))
import Stack exposing (topBelow)
topBelow 1 [ 2 ]
|> Stack.attach Down (topBelow -1 [ 0 ])
--> topBelow -1 [ 0, 1, 2 ]
topBelow 1 [ 2 ]
|> Stack.attach Down ([ -1, 0 ] |> Stack.fromList)
--> topBelow -1 [ 0, 1, 2 ]Be aware:
Down = indexes decreasing, not: from the top lowerUp = indexes increasing, not: from the bottom upCompared to attachAdapt
attach takes on the possiblyOrNever type of the incoming attachment StackattachAdapt takes on the possiblyOrNever type of the argumentGlue the elements of a given stack to the end in a given direction of the stack, taking on the emptiness knowledge of the given stack
import Linear exposing (Direction(..))
import Emptiable
import Stack exposing (topBelow)
Emptiable.empty
|> Stack.attachAdapt Down (topBelow 1 [ 2 ])
|> Stack.attachAdapt Down (topBelow -2 [ -1, 0 ])
--> topBelow -2 [ -1, 0, 1, 2 ]Be aware:
Down = indexes decreasing, not: from the top lowerUp = indexes increasing, not: from the bottom upCompared to attach
attach takes on the possiblyOrNever type of the incoming attachment StackattachAdapt takes on the possiblyOrNever type of the argumentGlue together a bunch of stacks
import Emptiable
import Stack exposing (topBelow)
topBelow
(topBelow 0 [ 1 ])
[ topBelow 10 [ 11 ]
, Emptiable.empty
, topBelow 20 [ 21, 22 ]
]
|> Stack.flatten
--> topBelow 0 [ 1, 10, 11, 20, 21, 22 ]For this to return a filled stack, all stacks must be filled
Change every element based on its current value and { index }
import Stack exposing (topBelow)
topBelow 1 [ 4, 9 ]
|> Stack.map (\_ -> negate)
--> topBelow -1 [ -4, -9 ]
topBelow 1 [ 2, 3, 4 ]
|> Stack.map (\{ index } n -> index * n)
--> topBelow 0 [ 2, 6, 12 ]Combine its elements with elements of a given stack at the same location. If one stack is longer, the extra elements are dropped
import Stack exposing (topBelow)
topBelow "alice" [ "bob", "chuck" ]
|> Stack.and (topBelow 2 [ 5, 7, 8 ])
--> topBelow ( "alice", 2 ) [ ( "bob", 5 ), ( "chuck", 7 ) ]
topBelow 4 [ 5, 6 ]
|> Stack.and (topBelow 1 [ 2, 3 ])
|> Stack.map (\_ ( n0, n1 ) -> n0 + n1)
--> topBelow 5 [ 7, 9 ]Reduce in a direction
import Linear exposing (Direction(..))
import Stack exposing (topBelow)
topBelow 'l' [ 'i', 'v', 'e' ]
|> Stack.foldFrom "" Down String.cons
--> "live"
topBelow 'l' [ 'i', 'v', 'e' ]
|> Stack.foldFrom "" Up String.cons
--> "evil"Be aware:
Down = indexes decreasing, not: from the top lowerUp = indexes increasing, not: from the bottom upFold, starting from one end element transformed to the initial accumulation value,
then reducing what's accumulated in a given Direction
Usually used to convert to or operate on a different non-empty structure
stackFilledReverse =
Stack.foldFromOne Stack.one Up Stack.onTopLay
-- module SetFilled exposing (SetFilled, fromStack, insert, one)
import Linear exposing (Direction(..))
import Emptiable exposing (Emptiable)
import Stack exposing (topBelow)
import Set exposing (Set)
fromStack : Emptiable (Stacked comparable) Never -> SetFilled comparable
fromStack =
Stack.foldFromOne one Up insert
type alias SetFilled comparable =
{ anElement : comparable
, otherElements : Set comparable
}
one : comparable -> SetFilled comparable
one onlyElement =
{ anElement = onlyElement, otherElements = Set.empty }
insert : comparable -> (SetFilled comparable -> SetFilled comparable)
insert toInsert =
\setFilled ->
if toInsert == setFilled.anElement then
setFilled
else
-- new element
{ setFilled
| otherElements =
setFilled.otherElements |> Set.insert toInsert
}
topBelow 3 [ 4, 5, 4, 3 ]
|> fromStack
--> { anElement = 3, otherElements = Set.fromList [ 5, 4 ] }(Know there's is something better than SetFilled: KeySet)
fold is a simple version that folds directly from the start element:
Stack.fold =
Stack.foldFromOne identityBe aware:
Down = indexes decreasing, not: from the top lowerUp = indexes increasing, not: from the bottom upFold, starting from one end as the initial accumulation value,
then reducing what's accumulated in a given Direction
import Linear exposing (Direction(..))
import Stack exposing (topBelow)
topBelow 234 [ 345, 543 ]
|> Stack.fold Up max
--> 543To fold into a different non-empty structure → Stack.foldFromOne
Be aware:
Down = indexes decreasing, not: from the top lowerUp = indexes increasing, not: from the bottom up∑ Total every element number
import Emptiable
topBelow 1 [ 2, 3 ] |> Stack.sum
--> 6
topBelow 1 (List.repeat 5 1) |> Stack.sum
--> 6
Emptiable.empty |> Stack.sum
--> 0Convert to a non-empty list tuple ( top, List belowElement )
to be used by another library
import Stack exposing (topBelow, toTopBelow)
topBelow "hi" [ "there", "👋" ]
|> toTopBelow
--> ( "hi", [ "there", "👋" ] )Don't use toTopBelow to destructure a stack.
Instead: Stack.top, Stack.removeTop
Convert to a List
import Stack exposing (topBelow)
topBelow 1 [ 7 ] |> Stack.toList
--> [ 1, 7 ]Don't try to use this prematurely. Keeping type information as long as possible is always a win
The representation of a non-empty stack on the
Filledcase.top,removeTop,onTopLayareO(n)in arguments
Emptiable(StackFilled ...) Never→stackis non-empty:in results
Emptiable(StackFilled ...)PossiblyEmpty→ stack could be emptyWe can treat it like any
Emptiable: