An Arr describes an array where you know more about the amount of elements.
Array.empty |> Array.get 0
--> Nothing
Arr.empty |> Arr.at nat0 FirstToLast
--> compile-time errorIs this any useful? Let's look at an example:
You have an array of 1+ elements. Get us the greatest value.
withArray : Array comparable -> Maybe comparable
withArray array =
array
|> Array.foldl
(\a mayB ->
case maybeC of
Just b ->
max a b
Nothing ->
a
)
Nothing
withArr : Arr (In (Nat1Plus minMinus1_) max_) comparable -> comparable
withArr =
Arr.foldWith FirstToLast maxThe Array type doesn't give us the info that it contains 1+ elements. Arr simply knows more about the length at compile time, so you can e.g. call foldWith without a worry.
Create an Arr from an Array.
As every Array has >= 0 elements:
Arr.fromArray arrayFromSomewhere
--> : Arr (Min Nat0)Don't use it this way:
Arr.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!
Arr.from7 0 1 2 3 4 5 6
--> ok
Arr.nats nat7
--> big yesConvert a non-empty list tuple into an Arr (Min Nat1).
Don't use it this way:
Arr.fromNonEmptyList ( 0, [ 1, 2, 3, 4, 5, 6 ] )
--> big no!Make sure the compiler knows as much as you about the amount of elements!
Arr.from7 0 1 2 3 4 5 6
--> ok
Arr.nats nat7
--> big yesShort for Array.fromList list |> Arr.fromArray. Convert a List to an Arr (Min Nat0).
Don't use it this way:
Arr.fromList [ 0, 1, 2, 3, 4, 5, 6 ]
--> big no!Make sure the compiler knows as much as you about the amount of elements!
Arr.from7 0 1 2 3 4 5 6
--> ok
Arr.nats nat7
--> big yesArr.from1 if Just, empty if Nothing.
Arr.fromMaybe (Just "hi")
--> Arr.from1 "hi"
--> : Arr (In Nat0 (Nat1Plus a_))
Arr.fromMaybe Nothing
--> Arr.empty
--> : Arr (In Nat0 (Nat1Plus a_))An Arr with a given amount of same elements.
Arr.repeat nat4 'L'
--> Arr.from4 'L' 'L' 'L' 'L'
Arr.repeat atLeast3 'L'
--> : Arr (Min Nat3) CharIncreasing natural numbers until below a given value.
Arr.nats nat4
--> Arr.from4 (Nat 0) (Nat 1) (Nat 2) (Nat 3)
--> : Arr
--> (In Nat4 (Nat4PLus a))
--> (Nat (In Nat0 (Nat3Plus a)))
Arr.nats between2And10
--> : Arr
--> (In Nat2 (Nat10Plus a))
--> (Nat (In Nat0 (Nat9Plus a)))
from first length =
Arr.nats length
|> Arr.map (InNat.add first)If you want to use a Nat as the length, but you don't know the maximum, e.g.
Arr.nats (Nat.intAtLeast nat5 someInt) -- erroruse minNats.
Increasing natural numbers until below a given value.
Use nats if you know the maximum length:
Arr.nats nat5
Arr.nats between2And10If you don't:
Arr.minNats atLeast10
--> : Arr (Min Nat10)
--> (Nat (Min Nat10))
from first length =
Arr.minNats length
|> Arr.map (MinNat.add first)Generate a given amount of elements and put them in an Arr.
Arr.random nat5 (Random.float 0 1)
--> : Random.Generator (Arr (In Nat5 (Nat5Plus a_)) Float)
Nat.randomNo elements.
Arr.empty
--> : Arr (In Nat0 atLeast0_) element
|> InArr.push ":)"
--> : Arr (In Nat1 (Nat1Plus atLeast0_)) StringCreate an Arr with exactly 1 element.
Create an Arr with exactly 2 elements in this order.
Create an Arr with exactly 3 elements in this order.
Create an Arr with exactly 4 elements in this order.
Create an Arr with exactly 5 elements in this order.
Create an Arr with exactly 6 elements in this order.
Create an Arr with exactly 7 elements in this order.
Create an Arr with exactly 8 elements in this order.
Create an Arr with exactly 9 elements in this order.
Create an Arr with exactly 10 elements in this order.
Create an Arr with exactly 11 elements in this order.
Create an Arr with exactly 12 elements in this order.
Create an Arr with exactly 13 elements in this order.
Create an Arr with exactly 14 elements in this order.
Create an Arr with exactly 15 elements in this order.
Create an Arr with exactly 16 elements in this order.
The amount of elements.
Arr.from3 1 2 3 |> Arr.length
--> nat3 : Nat (In Nat3 (Nat3Plus a_))
between3And5Elements |> Arr.length
--> : Nat (In Nat3 (Nat5Plus a_))
atLeast3Elements |> Arr.length
--> : Nat (Min Nat3)The element at a valid position in a direction.
Arr.from4 0 1 2 3
|> Arr.at nat1 FirstToLast
--> 1
Arr.from4 0 1 2 3
|> Arr.at nat1 LastToFirst
--> 2Whether all elements satisfy a test.
Arr.all isEven (Arr.from2 2 4)
--> True
Arr.all isEven (Arr.from2 2 3)
--> False
Arr.all isEven Arr.empty
--> TrueWhether any elements satisfy a test.
Arr.any isEven (Arr.from2 1 3)
--> True
Arr.any isEven (Arr.from2 1 2)
--> False
Arr.any isEven Arr.empty
--> FalseSet the element at an index in a direction.
Arr.from3 "I" "am" "ok"
|> Arr.replaceAt nat2 FirstToLast "confusion"
--> Arr.from3 "I" "am" "confusion"
Arr.from3 "I" "am" "ok"
|> Arr.replaceAt nat1 LastToFirst "feel"
--> Arr.from3 "I" "feel" "ok"An index that's out of bounds is ignored.
Arr.from3 "I" "am" "ok"
|> Arr.replaceAt nat3 LastToFirst "feel"
--> Arr.from3 "I" "am" "ok"Change the element at an index in a direction based on its previous value.
Arr.from3 1 20 30
|> Arr.updateAt nat0 FirstToLast ((*) 10)
--> Arr.from3 10 20 30
Arr.from3 1 20 30
|> Arr.updateAt nat0 LastToFirst (\x -> -x)
--> Arr.from3 1 20 -30An index that's out of bounds is ignored.
Arr.from3 1 20 30
|> Arr.updateAt nat3 FirstToLast ((*) 10)
--> Arr.from3 1 20 30Resize an Arr in a direction, padding with a given value.
Arr.from2 1 2
|> Arr.resize LastToFirst nat4 0
--> Arr.from4 0 0 1 2
Array.from3 1 2 3
|> Arr.resize LastToFirst nat2 0
--> Arr.from2 2 3
Array.from2 1 2
|> Arr.resize FirstToLast nat4 0
--> Arr.from4 1 2 0 0
Array.from3 1 2 3
|> Arr.resize FirstToLast nat2 0
--> Arr.from2 1 2This is a quick way to gain some type-level knowledge about the length.
Alias to Arr.order LastToFirst: flip the order of the elements.
Arr.from4 "l" "i" "v" "e"
|> Arr.reverse
--> Arr.from4 "e" "v" "i" "l"Keep the order if FirstToLast,
reverse if LastToFirst.
Arr.from3 1 2 3
|> Arr.order LastToFirst
--> Arr.from3 3 2 1
Arr.from3 1 2 3
|> Arr.order FirstToLast
--> Arr.from3 1 2 3Only keep values that satisfy a test.
Arr.from5 1 2 3 4 5
|> Arr.when (\n -> n >= 3)
--> Arr.from3 3 4 5
--> : Arr (In Nat0 (Nat5Plus a_)) number_Remove values where a condition is met.
Arr.from5 1 2 3 4 5
|> Arr.dropWhen (\n -> n < 3)
--> Arr.from3 3 4 5
--> : Arr (In Nat0 (Nat5Plus a_)) number_Take every Just value & drop every Nothing.
Arr.from3 (Just "This") Nothing (Just "fine")
|> Arr.whenJust
--> Arr.from2 "This" "fine"
--> : Arr (In Nat0 (Nat3Plus a_)) StringCall map and then whenJust to get the same functionality as "filterMap".
Arr.from3 "1.2" "2" "hello"
|> Arr.map String.toInt
|> Arr.whenJust
--> Arr.from1 2
--> : Arr (In Nat0 (Nat3Plus a_)) IntIf every Maybe is present, return all of the values. Return Nothing if any element is Nothing.
Arr.empty |> Arr.whenAllJust
--> Just Arr.empty
Arr.from3 (Just 1) (Just 2) (Just 3)
|> Arr.whenAllJust
--> Just (Arr.from3 1 2 3)
Arr.from3 (Just 1) Nothing (Just 3)
|> Arr.whenAllJust
--> NothingFunnily, this can sometimes even be nicer than Maybe.mapN:
groupCall =
Arr.from5 aUser bUser cUser dUser eUser
|> Arr.map .phoneNumber
|> Arr.whenAllJust
-- vs
groupCall =
Maybe.map5 Toop.T5
aUser.phoneNumber
bUser.phoneNumber
cUser.phoneNumber
dUser.phoneNumber
eUser.phoneNumberA certain number of elements from a direction.
Arr.from8 0 1 2 3 4 5 6 7
|> Arr.takeMax nat7 between3And7 FirstToLast
--> : Arr (In Nat3 (Nat7Plus a_)) ...The first number is the maximum taken amount. The second number is the amount of taken elements.
Use take if you know the exact amount of elements to take.
Split the Arr into equal-sized chunks in a direction.
groups: the Arr divided into equal-sized Arrsless: values to one side that don't fill a whole groupArr.from7 1 2 3 4 5 6 7
|> Arr.groupsOf nat5 FirstToLast
--> { groups =
--> Arr.from1 (Arr.from5 1 2 3 4 5)
--> : Arr (In Nat0 (Nat7Plus a_))
--> (Arr (In Nat5 (Nat5Plus b_)) number_)
--> , remaining =
--> Arr.from2 6 7
--> : Arr (In Nat0 (Nat5Plus c_)) number_
--> }
Arr.from7 1 2 3 4 5 6 7
|> Arr.groupsOf nat5 LastToFirst
--> { groups = Arr.from1 (Arr.from5 3 4 5 6 7) : ...
--> , remaining = Arr.from2 1 2 : ...
--> }Change every element.
aToZ : Arr (In Nat26 (Nat26Plus a_)) Char
aToZ =
Arr.nats nat26
|> Arr.map (val >> inABC)
inABC index =
('a' |> Char.toCode)
+ index
|> Char.fromCodeval refers to Typed.val.
A fold in a direction where the initial result is the first value in the Arr.
Arr.from3 234 345 543
|> Arr.foldWith FirstToLast max
--> 543
Arr.foldWith LastToFirst
(\word soFar -> soFar ++ " " ++ word)
(Arr.from3 "go" "to" "school")
--> "school to go"Reduce an Arr in a direction.
Arr.from5 'l' 'i' 'v' 'e'
|> Arr.fold LastToFirst String.cons ""
--> "live"
Arr.from5 'l' 'i' 'v' 'e'
|> Arr.fold FirstToLast String.cons ""
--> "evil"
sum =
Arr.fold FirstToLast (+) 0
product =
Arr.fold FirstToLast (*) 0Convert the Arr to an Array.
Just do this in the end.
Try to keep extra information as long as you can.
Arr.nats nat5
|> Arr.map val
|> Arr.toArray
--> Array.fromList [ 0, 1, 2, 3, 4 ]val refers to Typed.val.
Convert the Arr to a List.
Make these kinds of operations the final step.
Try to keep extra information as long as you can.
Arr.nats nat5
|> Arr.map val
|> Arr.toNonEmptyList
--> ( 0, [ 1, 2, 3, 4 ] )val refers to Typed.val.
Short for Arr.toArray arr |> Array.toList. Convert the Arr to a List.
Make these kinds of operations the final step.
Try to keep extra information as long as you can.
Arr.nats nat5
|> Arr.map val
|> Arr.toList
--> [ 0, 1, 2, 3, 4 ]val refers to Typed.val.
Nothing if the Arr is empty, else Just it's only value.
Access the only value in the Arr.
Arr.to1 (Arr.from1 "hi")
--> "hi"Transform the Arr into a Toop.T2. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T3. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T4. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T5. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T6. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T7. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T8. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T9. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T10. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T11. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T12. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T13. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T14. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T15. This makes accessing elements and pattern matching easier.
Transform the Arr into a Toop.T16. This makes accessing elements and pattern matching easier.
Combine the elements of 2 Arrs into new elements.
If one list is longer, its extra elements are not used.
teamLives aBoard bBoard =
Arr.map2 (\a b -> a.lives + b.lives)
aBoard
bBoardThe length of all Arrs must be in the same range.
Arr's maximum length isn't known:Arr.map2 (\a b -> a.lives + b.lives)
(aBoard |> Arr.toMin)
(bBoard |> Arr.toMin)
aBoard : Arr (In Nat2 someMax_) Field
bBoard : Arr (In Nat2 otherMax_) FieldArr has a higher minimum length:Arr.map2 (\a b -> a.lives + b.lives)
(aBoard |> Arr.lowerMinLength nat2)
bBoard
aBoard : Arr (In Nat5 Nat10) FieldCombine the elements of 3 Arrs into new elements. Works like map2.
Combine the elements of 4 Arrs into new elements. Works like map2.
Use a lower minimum length in the type.
[ atLeast3Elements
, atLeast4Elements
]Elm complains:
But all the previous elements in the list are
Arr (Min Nat3) ...
[ atLeast3Elements
, atLeast4Elements
|> Arr.lowerMinLength nat3
]Convert the Arr (In min ...) to a Arr (Min min).
between4And10Elements |> Arr.toMin
--> : Arr (Min Nat4) ...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
Arr (Min Nat1) ...
[ atLeast1Element
, between1And10Elements |> Arr.toMin
]Make an Arr with a fixed maximum length fit into functions with require a higher maximum length.
While designing argument annotations as general as possible:
atMost18Elements : Arr (In min_ Nat18) ...The argument in atMost18Elements should also fit in atMost19Elements.
atMost19Elements theArgument
--> error :(
atMost19Elements
(theArgument |> Arr.restoreMaxLength nat18)
--> worksAn error for when a decoded array doesn't have the expected length.
You can transform it into a message with errorToString.
See the serialize functions.
An expectation for the decoded array that hasn't been met.
ExpectLength: expected a different exact lengthLengthInBound: expected a length within a range (→ see InNat.Expectation)ExpectAtLeast some minimum in a rangeExpectAtMost some maximum in a rangeSee errorToString and the serialize functions.
Convert an error to a readable message.
{ expected = Arr.ExpectLength nat11
, actual = { length = nat10 }
}
|> Arr.errorToString
--> "Expected an array of length 11, but the actual length was 10."(example doesn't compile)
An
Arrdescribes an array where you know more about the amount of elements.types
as argument types
as storage types
To store in your
Modelfor example (which means: no type variables)