An Array that knows more about the amount of elements it holds.
import Linear exposing (DirectionLinear(..))
import N exposing (n0)
import Array
Array.empty |> Array.get 0
--> Nothing
ArraySized.empty |> ArraySized.element ( Up, n0 )
-- compile-time errorIs this any useful? One example:
You have an array of 1+ elements. What's its greatest value?
withArray : Array comparable -> Maybe comparable
withArray =
Array.foldl
(\element soFar ->
case soFar of
Just maxSoFar ->
max maxSoFar element
Nothing ->
element
)
Nothing
withArraySized :
ArraySized (In (Add1 minMinus1_) max_) comparable
-> comparable
withArraySized =
ArraySized.fold Up Basics.maxThe Array type can't express it contains 1+ elements.
ArraySized knows about its length at compile time,
so we can fold, access, ... without a worry
Exactly the given amount of same elements
import N exposing (n4)
ArraySized.repeat 'L' n4
--: ArraySized
--: (In
--: (Up minX To (Add4 minX))
--: (Up maxX To (Add4 maxX))
--: )
--: Char
|> ArraySized.toList
--> [ 'L', 'L', 'L', 'L' ]
ArraySized.repeat 'L' atLeast3
--: ArraySized (Min (Up x To (Add3 x))) CharRandom.Generator for the given amount of random elements
import N exposing (n5)
ArraySized.random (Random.float 0 1) n5
--: Random.Generator
--: (ArraySized
--: (In
--: (Up minX To (Add5 minX))
--: (Up maxX To (Add5 maxX))
-->: )
--: Float
--: )Pairs really well with
N.randomIn ( <length min>, <length max> )
|> Random.andThen
(ArraySized.random <element>)Increasing natural numbers until including a given number
import N exposing (n3)
ArraySized.until n3
--: ArraySized
--: (In (Fixed N4) (Up maxX To (Add4 maxX)))
--: (N (In (Up minX To minX) (Up maxX To (Add3 maxX))))
|> ArraySized.map N.toInt
|> ArraySized.toList
--> [ 0, 1, 2, 3 ]
ArraySized.until between2And9
|> ArraySized.map (N.add n3)
--: ArraySized
--: (In (Fixed N3) (Up maxX To (Add10 maxX)))
--: (N (In (Up minX To (Add5 minX)) (Up maxX To (Add12 maxX))))min is helpful
to turn the Fixed length minimum into a difference
if you need that (for results etc.)
Create from an Array.
As every Array has >= 0 elements:
arrayFromSomeOtherLibrary |> ArraySized.fromArray
--: ArraySized (Min (Up x To x))Don't use it for construction:
ArraySized.fromArray
(Array.fromList [ 0, 1, 2, 3, 4, 5, 6 ])
-- big noMake sure the compiler knows as much as you about the amount of elements!
ArraySized.l7 0 1 2 3 4 5 6 -- ok
ArraySized.until n6 -- big yesCreate from a List.
As every List has >= 0 elements:
listFromSomeOtherLibrary |> ArraySized.fromList
--: ArraySized (Min (Up x To x))Don't use for construction:
ArraySized.fromList [ 0, 1, 2, 3, 4, 5, 6 ]
-- big no!Make sure the compiler knows as much as you about the amount of elements!
ArraySized.l7 0 1 2 3 4 5 6 -- ok
ArraySized.until n6 -- big yesOn Just ArraySized.l1, on Nothing empty
import N exposing (n0)
import Emptiable exposing (filled)
filled "hi"
|> ArraySized.fromEmptiable
--: ArraySized
--: (In (Up minX To minX) (Up maxX To (Add1 maxX)))
|> ArraySized.toList
--> [ "hi" ]
Emptiable.empty
|> ArraySized.fromEmptiable
--: ArraySized
--: (In (Up minX To minX) (Up maxX To (Add1 maxX)))
|> ArraySized.toList
--> []Sadly, they way natural number constraints are defined,
possiblyOrNever can't be transferred.
Create from a Stack.
As every Stack has >= 0 elements:
listFromSomeOtherLibrary |> ArraySized.fromStackFilled
--: ArraySized (Min (Up x To (Add1 x)))Don't use for construction:
ArraySized.fromStackFilled (Stack.topDown 0 [ 1, 2, 3, 4, 5, 6 ])
-- big no!Make sure the compiler knows as much as you about the amount of elements!
ArraySized.l7 0 1 2 3 4 5 6 -- ok
ArraySized.until n6 -- big yesOnly have an Emptiable (Stacked ...) Possibly? → fromStackEmptiable
Create from a Stack.
As every Stack has >= 0 elements:
listFromSomeOtherLibrary |> ArraySized.fromStackEmptiable
--: ArraySized (Min (Up x To x))Don't use for construction:
ArraySized.fromStackEmptiable
(Stack.fromList [ 0, 1, 2, 3, 4, 5, 6 ])
-- big no!Make sure the compiler knows as much as you about the amount of elements!
ArraySized.l7 0 1 2 3 4 5 6 -- ok
ArraySized.until n6 -- big yesHave an Emptiable (Stacked ...) Never? → fromStackFilled
No elements
ArraySized.empty
--: ArraySized (Up minX To minX) (Up maxX To maxX) element_
|> ArraySized.push ":)"
--: ArraySized
--: (Up minX To (Add1 minX)) (Up maxX To (Add1 maxX))
--: StringCreate an ArraySized with exactly 1 element
Create an ArraySized with exactly 2 elements in this order
Create an ArraySized with exactly 3 elements in this order
Create an ArraySized with exactly 4 elements in this order
Create an ArraySized with exactly 5 elements in this order
Create an ArraySized with exactly 6 elements in this order
Create an ArraySized with exactly 7 elements in this order
Create an ArraySized with exactly 8 elements in this order
Create an ArraySized with exactly 9 elements in this order
Create an ArraySized with exactly 10 elements in this order
Create an ArraySized with exactly 11 elements in this order
Create an ArraySized with exactly 12 elements in this order
Create an ArraySized with exactly 13 elements in this order
Create an ArraySized with exactly 14 elements in this order
Create an ArraySized with exactly 15 elements in this order
Create an ArraySized with exactly 16 elements in this order
You can generate l<x> with x >= 17 locally,
put them in a module exposing (l<x>) + import as ArraySized
The amount of elements.
import N exposing (n3)
ArraySized.l3 1 2 3
|> ArraySized.length
--: N
--: (In
--: (Up minX To (Add3 minX))
--: (Up maxX To (Add3 maxX))
--: )
|> N.toInt
--> 3
between3And5Elements |> ArraySized.length
--: N
--: (In
--: (Up minX To (Add3 minX))
--: (Up maxX To (Add5 maxX))
--: )
atLeast3Elements |> ArraySized.length
--: N (Min (Up minX To (Add3 minX)))Its element at a valid location in a direction
import Linear exposing (DirectionLinear(..))
import N exposing (n1)
ArraySized.l4 0 1 2 3
|> ArraySized.element ( Up, n1 )
--> 1
ArraySized.l4 0 1 2 3
|> ArraySized.element ( Down, n1 )
--> 2Its possible element at a location
in a direction.
Because the index doesn't promise it's <= the ArraySized's length minimum,
elementTry gives back a Result
import Linear exposing (DirectionLinear(..))
import N exposing (n1, n5)
ArraySized.l4 0 1 2 3
|> ArraySized.elementTry ( Up, n5 )
--> Err (Linear.ExpectedIndexForLength 4)
ArraySized.l4 0 1 2 3
|> ArraySized.elementTry ( Down, n1 )
--> Ok 2Its only value
ArraySized.l1 "hi" |> ArraySized.to1
--> "hi"Whether all elements satisfy a given test
ArraySized.l2 2 3 |> ArraySized.allAre (\n -> n <= 4)
--> True
ArraySized.l2 2 7 |> ArraySized.allAre (\n -> n <= 4)
--> False
ArraySized.empty |> ArraySized.allAre (\n -> n <= 4)
--> TrueWhether at least one element satisfies a given test
ArraySized.l2 300 -5 |> ArraySized.anyIs (\n -> n <= 4)
--> True
ArraySized.l2 5 5 |> ArraySized.anyIs (\n -> n <= 4)
--> False
ArraySized.empty |> ArraySized.anyIs (\n -> n <= 4)
--> FalseSet the element at an index in a direction
import Linear exposing (DirectionLinear(..))
import N exposing (n1, n2)
ArraySized.l3 "I" "am" "ok"
|> ArraySized.elementReplace ( Up, n2 )
(\() -> "confusion")
|> ArraySized.toList
--> [ "I", "am", "confusion" ]
ArraySized.l3 "I" "am" "ok"
|> ArraySized.elementReplace ( Down, n1 )
(\() -> "feel")
|> ArraySized.toList
--> [ "I", "feel", "ok" ]An index that's too high to point to an existing element is ignored and no element is replaced
import Linear exposing (DirectionLinear(..))
import N exposing (n3)
ArraySized.l3 "I" "am" "ok"
|> ArraySized.elementReplace ( Down, n3 )
(\() -> "feel")
|> ArraySized.toList
--> [ "I", "am", "ok" ]Change the element at an index in a direction based on its previous value
import Linear exposing (DirectionLinear(..))
import N exposing (n0)
ArraySized.l3 1 20 30
|> ArraySized.elementAlter ( Up, n0 ) (\x -> x * 10)
|> ArraySized.toList
--> [ 10, 20, 30 ]
ArraySized.l3 1 20 30
|> ArraySized.elementAlter ( Down, n0 ) negate
|> ArraySized.toList
--> [ 1, 20, -30 ]An index that's too high to point to an existing element is ignored and no element is altered
import Linear exposing (DirectionLinear(..))
import N exposing (n3)
ArraySized.l3 1 20 30
|> ArraySized.elementAlter ( Up, n3 ) (\x -> x * 10)
|> ArraySized.toList
--> [ 1, 20, 30 ]Flip the order of the elements
ArraySized.l4 "l" "i" "v" "e"
|> ArraySized.reverse
|> ArraySized.toList
--> [ "e", "v", "i", "l" ]Put a new element after all the others
between5And10Elements
|> ArraySized.push "becomes the last"
--: ArraySized
--: (In
--: (Up minX To (Add6 minX))
--: (Up maxX To (Add11 maxX))
--: )
--: StringminPush if you don't know the length maximum
Put a new element after all the others
atLeast5Elements
|> ArraySized.minPush "becomes the last"
--: ArraySized (Min (Up minX To (Add6 minX))) Stringpush if you know the length maximum
Put an element in the ArraySized at a given index
in a direction
import Linear exposing (DirectionLinear(..))
import N exposing (n1, n2)
ArraySized.l3 'a' 'c' 'd'
|> ArraySized.insert ( Up, n1 ) 'b'
--: ArraySized
--: (In (Fixed N4) (Up maxX To (Add4 maxX)))
--: Char
|> ArraySized.toList
--> [ 'a', 'b', 'c', 'd' ]
ArraySized.l3 'a' 'c' 'd'
|> ArraySized.insert ( Down, n2 ) 'b'
|> ArraySized.toList
--> [ 'a', 'b', 'c', 'd' ]minInsert if you don't know the length maximum
Need the length minimum to not become Fixed
(for results etc.) → |> min
Put a new element at an index in a direction.
import Linear exposing (DirectionLinear(..))
import N exposing (n0, n1)
atLeast5Elements
|> ArraySized.minInsert ( Down, n1 ) "before last"
--: ArraySized (Min (Fixed N6)) String
minCons :
element
-> ArraySized (In (Fixed min) max_) element
-> ArraySized (Min (Fixed (Add1 min))) element
minCons =
ArraySized.minInsert ( Up, n0 )insert if you know the length maximum
Need the length minimum to not become Fixed
(for results etc.) → |> min
Kick out the element at a given index in a direction
import Linear exposing (DirectionLinear(..))
import N exposing (n0)
removeLast between1And10Elements =
between1And10Elements
|> ArraySized.elementRemove ( Down, n0 )Don't know the length maximum? → minElementRemove
Kick out the element at an index in a direction.
removeLast =
TypeSized.minElementRemove ( Down, n0 )Know the length maximum? → minElementRemove
Take every filled value, drop every empty
import Emptiable exposing (filled)
ArraySized.l3 (filled "This") Emptiable.empty (filled "fine")
|> ArraySized.fills
--: ArraySized
--: (In (Up minX To minX) (Up maxX To (Add3 maxX)))
--: String
|> ArraySized.toList
--> [ "This", "fine" ]map |> fills to get the same functionality as "filterMap"
import Emptiable
ArraySized.l3 "1.2" "2" "hello"
|> ArraySized.map (String.toInt >> Emptiable.fromMaybe)
|> ArraySized.fills
|> ArraySized.toList
--> [ 2 ]If every Emptiable is filled, all of the values.
If any element is empty, empty
import Emptiable exposing (filled, fillMap)
ArraySized.empty
|> ArraySized.allFill
|> fillMap ArraySized.toList
--> filled []
ArraySized.l3 (filled 1) (filled 2) (filled 3)
|> ArraySized.allFill
|> fillMap ArraySized.toList
--> filled [ 1, 2, 3 ]
ArraySized.l3 (filled 1) Emptiable.empty (filled 3)
|> ArraySized.allFill
--> Emptiable.emptyFunnily, this can sometimes even be nicer than mapN/andMap
groupCall =
ArraySized.l5 aUser bUser cUser dUser eUser
|> ArraySized.map .phoneNumber
|> ArraySized.allFill
-- vs
groupCall =
map5 ArraySized.l5
aUser.phoneNumber
bUser.phoneNumber
cUser.phoneNumber
dUser.phoneNumber
eUser.phoneNumberA given number of elements to a given direction.
An atLeast argument is sadly required to proof the taken minimum
isn't above the ArraySized's length minimum
import Linear exposing (DirectionLinear(..))
import N exposing (n7)
ArraySized.l8 0 1 2 3 4 5 6 7
|> ArraySized.take ( Up, n7, { atLeast = n7 } )
--: ArraySized
--: (In (Up minX To (Add7 minX)) (Up maxX To (Add7 maxX)))
--: number_
|> ArraySized.toList
--> [ 0, 1, 2, 3, 4, 5, 6 ]
ArraySized.l8 0 1 2 3 4 5 6 7
|> ArraySized.take ( Up, n7AtLeast, { atLeast = n7 } )
--: ArraySized (Min (Up x To (Add7 x))) number_
ArraySized.l8 0 1 2 3 4 5 6 7
|> ArraySized.take ( Up, between2And7, { atLeast = n2 } )
--: ArraySized
--: (In (Up minX To (Add2 minX)) (Up maxX To (Add7 maxX)))
--: number_Elements after a certain number of elements in a direction.
import Linear exposing (DirectionLinear(..))
import N exposing (n2)
ArraySized.l4 0 1 2 3
|> ArraySized.drop ( Down, n2 )
--: ArraySized
--: (In
--: (Up minX To (Add2 minX))
--: (Up maxX To (Add2 maxX))
--: )
--: number_
|> ArraySized.toList
--> [ 0, 1 ]
between6And10Elements
|> ArraySized.drop ( Up, between2And3 )
--: ArraySized
--: (In
--: (Up minX To (Add3 minX))
--: (Up maxX To (Add8 maxX))
--: )
--: number_Don't know its length maximum? → minDrop
Split the ArraySized into equal-sized (except remainder) slices
in a direction
groups: the ArraySized divided into equal-sized Arrsless: values to one side that don't fill a whole group↓
import Linear exposing (DirectionLinear(..))
import N exposing (n0, n5)
ArraySized.l7 1 2 3 4 5 6 7
|> ArraySized.toChunksOf n5 { remainder = Up }
--: { chunks :
--: ArraySized
--: (In (Up minX To minX) (Up maxX To (Add7 maxX)))
--: (ArraySized
--: (In
--: (Up chunkMinX To (Add5 chunkMinX))
--: (Up chunkMaxX To (Add5 chunkMaxX))
--: )
--: number_
--: )
--: , remainder :
--: ArraySized
--: (In
--: (Up minX To minX)
--: (Up chunkMaxX To (Add5 chunkMaxX))
--: )
--: number_
--: }
|> .remainder
|> ArraySized.toList
--> [ 6, 7 ]
ArraySized.l7 1 2 3 4 5 6 7
|> ArraySized.toChunksOf n5 { remainder = Down }
|> .remainder
|> ArraySized.toList
--> [ 1, 2 ]Attach elements of an ArraySized with an exact amount of elements to a given direction.
import Linear exposing (DirectionLinear(..))
ArraySized.l3 1 2 3
|> ArraySized.glue Up (ArraySized.l3 4 5 6)
--: ArraySized
--: (In
--: (Up minX To (Add6 minX))
--: (Up maxX To (Add6 maxX))
--: )
--: number_
|> ArraySized.toList
--> [ 1, 2, 3, 4, 5, 6 ]
ArraySized.l3 1 2 3
|> ArraySized.glue Down (ArraySized.l3 4 5 6)
|> ArraySized.toList
--> [ 4, 5, 6, 1, 2, 3 ]Don't know both length maxima? → minGlue
Attach elements of an ArraySized
to the end in a given direction
ArraySized.l3 1 2 3
|> ArraySized.minGlue Up atLeast3Elements
--: ArraySized (Min (Up x To (Add6 x))) ...
ArraySized.l3 1 2 3
|> ArraySized.minGlue Down atLeast3Elements
--: ArraySized (Min (Up x To (Add6 x))) ...Know both length maxima? → glue
Place all elements of an ArraySized
between all current members.
Extra elements of either ArraySized are glued to the end
without separating elements from the other ArraySized.
import N exposing (n2)
ArraySized.l3 "turtles" "turtles" "turtles"
|> ArraySized.interweave (ArraySized.repeat "on" n2)
--: ArraySized
--: (In
--: (Up minX To (Add5 minX))
--: (Up maxX To (Add5 maxX))
--: )
--: String
|> ArraySized.toList
--> [ "turtles", "on", "turtles", "on", "turtles" ]
ArraySized.l3 "turtles" "turtles" "turtles"
|> ArraySized.interweave (ArraySized.repeat "on" between5And10)
--→ "turtles" "on" "turtles" "on" "turtles" "on" "on" "on" ...
--: ArraySized
--: (In
--: (Up minX To (Add5 minX))
--: (Up maxX To (Add13 maxX))
--: )
--: StringDon't know both maxima → minInterweave
Place all elements of an ArraySized
between all current members.
Extra elements of either ArraySized are glued to the end
without separating elements from the other ArraySized.
import N exposing (n2)
ArraySized.l3 "turtles" "turtles" "turtles"
|> ArraySized.minInterweave (ArraySized.repeat "on" atLeast2)
--: ArraySized
--: (Min
--: (Up minX To (Add5 minX))
--: )
--: StringKnow both maxima → interweave
Compared to a range from a lower to an upper bound, is its length in, BelowOrAbove range?
import N exposing (n10, n16)
chooseFormation :
ArraySized (In minLength_ N50) Character
-> Formation
chooseFormation characters =
case characters |> ArraySized.hasIn ( n10, n16 ) of
Ok between10And16 ->
SpecialAttack between10And16
Err (N.Below n9AtMost) ->
Retreat n9AtMost
Err (N.Above n17AtLeast) ->
Fight n17AtLeastCompare its length to a given exact length. Does it match or is it BelowOrAbove?
import N exposing (n7)
chooseFormation :
ArraySized (In min N50) Character
-> Formation
chooseFormation characters =
case characters |> ArraySized.has n7 of
Ok exactly7 ->
SpecialAttack exactly7
Err (N.Below l6AtLeast) ->
Retreat l6AtLeast
Err (N.Above l8AtLeast) ->
Fight l8AtLeastIs its length below (Err) or atLeast (Ok) as big as a given N?
import N exposing (n5)
first5 :
ArraySized (In minLength_ max) element
-> Maybe (ArraySized (In N5 max) element)
first5 arraySized =
case arraySized |> ArraySized.hasAtLeast n5 of
N.Below _ ->
Nothing
N.EqualOrGreater atLeast5 ->
Just atLeast5Is its length atMost (Ok) or above (Err) a given length?
-- at least 3 and only up to 50 tags
tag :
ArraySized (In (Add3 orHigherMin_) N50) String
-> a
-> Tagged a
tagIfValidTags :
ArraySized (In (Add3 orHigherMin_) max)
-> a
-> Maybe (Tagged a)
tagIfValidTags array value =
case
array
|> ArraySized.fromArray
|> ArraySized.hasAtMost n50
of
Ok atMost53 ->
tag value atMost53 |> Just
Err _ ->
NothingChange every element.
import N exposing (n25)
aToZ : ArraySized (In N26 (N26Plus a_)) Char
aToZ =
ArraySized.until n25
|> ArraySized.map inABC
inABC index =
('a' |> Char.toCode)
+ (index |> N.toInt)
|> Char.fromCodeOh look, more type-safety!
Reduce an ArraySized in a direction.
import Linear exposing (DirectionLinear(..))
ArraySized.l4 'l' 'i' 'v' 'e'
|> ArraySized.foldFrom "" Down String.cons
--> "live"
ArraySized.l4 'l' 'i' 'v' 'e'
|> ArraySized.foldFrom "" Up String.cons
--> "evil"
sum =
ArraySized.foldFrom 0 Up (\soFar n -> soFar + n)
product =
ArraySized.foldFrom 0 Up (\soFar n -> soFar * n)A fold in a direction
where the initial result is the first element in the ArraySized.
import Linear exposing (DirectionLinear(..))
ArraySized.l3 234 345 543
|> ArraySized.fold Up Basics.max
--> 543
ArraySized.l3 "go" "to" "uni"
|> ArraySized.fold Down
(\word soFar -> soFar ++ " " ++ word)
--> "uni to go"Convert to an Array.
Make these kinds of conversions your final step.
Try to keep extra information as long as you can: "wrap early, unwrap late"
import N exposing (n4)
import Array
ArraySized.until n4
|> ArraySized.map N.toInt
|> ArraySized.toArray
--> Array.fromList [ 0, 1, 2, 3, 4 ]Convert to a List.
Make these kinds of conversions your final step.
Try to keep extra information as long as you can: "wrap early, unwrap late"
import N exposing (n4)
ArraySized.until n4
|> ArraySized.map N.toInt
|> ArraySized.toList
--> [ 0, 1, 2, 3, 4 ]Convert to an Emptiable (Stacked ...) Possibly.
Make these kinds of conversions your final step.
Try to keep extra information as long as you can: "wrap early, unwrap late"
import N exposing (n4)
ArraySized.until n4
|> ArraySized.map N.toInt
|> ArraySized.toStackEmptiable
--> Stack.topDown [ 0, 1, 2, 3, 4 ]
--: Emptiable (Stacked Int) PossiblyHave >= 1 element? → Keep an Emptiable ... never_ toStackFilled
Convert to an Emptiable (Stacked ...) never_.
Make these kinds of conversions your final step.
Try to keep extra information as long as you can: "wrap early, unwrap late"
import N exposing (n4)
ArraySized.until n4
|> ArraySized.map N.toInt
|> ArraySized.toStackFilled
--> Stack.topDown [ 0, 1, 2, 3, 4 ]
--: Emptiable (Stacked Int) NeverDon't have >= 1 element? → toStackEmptiable
You have a use-case for mapAccumulate/mapAccumulateFrom? → issue/PR
Transform the ArraySized into a Toop.T2. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T3. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T4. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T5. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T6. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T7. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T8. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T9. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T10. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T11. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T12. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T13. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T14. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T15. This makes accessing elements and pattern matching easier.
Transform the ArraySized into a Toop.T16. This makes accessing elements and pattern matching easier.
You can generate to<x> with x >= 17 locally,
put them in a module exposing (to<x>) + import as ArraySized
Use a lower minimum length in the type.
[ atLeast3Elements
, atLeast4Elements
]elm complains that
all the previous elements in the list are
ArraySized (Min N3) ...
[ atLeast3Elements
, atLeast4Elements
|> ArraySized.minDownLength n3
]Convert the ArraySized (In min ...) to a ArraySized (Min min).
between4And10Elements |> ArraySized.toMin
--: ArraySized (Min N4) ...There is only 1 situation you should use this.
To make these the same type.
[ atLeast1Element, between1And10Elements ]Elm complains:
But all the previous elements in the list are
ArraySized (Min N1) ...
[ atLeast1Element
, between1And10Elements |> ArraySized.toMin
]Make an ArraySized with a fixed maximum length fit into functions with require a higher maximum length.
type alias Row =
ArraySized (Exactly N18) FieldRow's length range can't be added to another length.
glue2TemporaryFields : Row -> ...
glue2TemporaryFields rowFromModelOrSomeStorage =
ArraySized.repeat Temporary n2
|> ArraySized.glue Up rowFromModelOrSomeStorageOnly Up x To (Add<n> x) can do that:
glue2TemporaryFields :
Row
->
ArraySized
(In
(Up minX To (Add20 minX))
(Up maxX To (Add20 maxX))
)
Field
glue2TemporaryFields rowFromModelOrSomeStorage =
ArraySized.repeat Temporary n2
|> ArraySized.glue Up
(rowFromModelOrSomeStorage
|> ArraySized.min n18
|> ArraySized.max n18
)Another example: re-enabling an argument's maximum difference
atMost18Elements : ArraySized (In min_ (Up maxTo18_ To N18)) ...The argument in atMost18Elements should also fit in atMost19Elements for example
atMost19Elements theArgument -- error
atMost19Elements (theArgument |> ArraySized.max n19)maxUp n1 is also possible,
but unless you want to preserve the maxTo18_ type variable,
there's no need to not use this absolute operation.
Make an ArraySized with a fixed maximum length fit into functions with require a higher maximum length.
type alias Row =
ArraySized (Exactly N18) FieldRow's length range can't be added to another length.
glue2TemporaryFields : Row -> ...
glue2TemporaryFields rowFromModelOrSomeStorage =
ArraySized.repeat Temporary n2
|> ArraySized.glue Up rowFromModelOrSomeStorageOnly Up x To (Add<n> x) can do that:
glue2TemporaryFields :
Row
->
ArraySized
(In
(Up minX To (Add20 minX))
(Up maxX To (Add20 maxX))
)
Field
glue2TemporaryFields rowFromModelOrSomeStorage =
ArraySized.repeat Temporary n2
|> ArraySized.glue Up
(rowFromModelOrSomeStorage
|> ArraySized.min n18
|> ArraySized.max n18
)
An
Arraythat knows about the amount of elements it holdsresult type
This weird difference type
Up x To (Add<n> x)just to represent the numbernis what allows the little magic tricks in the library: glueing, taking, dropping, chunking, comparing, ...argument type
to allow the broadest range of desired lengths,
+some variableUpa variable amount to arrive at the desired maximum numberstored type
in your
Modelfor example. They look just like result types but everyUp x To (Add<n> x)becomesFixed N<n>, avoiding type variablesExactly nbeing a shorthand for==on ranges can crash elm. Use the safe comparison methods