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:
0 to 100 joined by a space
joinBy between =
\before after -> before ++ between ++ after
let
intStringsAfter =
Array.fromList (List.range 1 100)
String.fromInt
in
Array.foldl (joinBy " ") "0" intStringsAfter
--> "0 1 2 3 4 5 ..."
Arr.nats nat100
|> Arr.map (val >> String.fromInt)
|> Arr.foldWith FirstToLast (joinBy " ")
--> "0 1 2 3 4 5 ..."The Array version just seems hacky and is less readable. 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 noTell the compiler if you know the amount of elements. Make sure the it knows as much as you!
Arr.from7 0 1 2 3 4 5 6
--> ok
Arr.nats nat7
--> big yesAn Arr with a given amount of same elements.
Arr.repeat nat4 'L'
--> Arr.from4 'L' 'L' 'L' 'L'
--> : Arr (In Nat4 (Nat4Plus a)) Char
Arr.repeat atLeast3 'L'
--> : Arr (Min Nat3) CharIncreasing natural numbers. In the end, there are length numbers.
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 dont know the maximum, e.g.
Arr.nats (Nat.intAtLeast nat5 someInt) -- erroruse minNats.
Increasing natural numbers. In the end, there are length numbers. Use nats if you know the maximum length.
Arr.nats nat5
Arr.nats between2And10If not:
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.
No 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.
The element at a valid position in a direction.
Arr.from4 1 2 3 4
|> Arr.at nat1 FirstToLast
--> 2
Arr.from4 1 2 3 4
|> Arr.at nat1 LastToFirst
--> 3Set 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"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 10 20 -30
|> Arr.updateAt nat0 LastToFirst (\x -> -x)
--> Arr.from3 10 20 30Only keep values that satisfy a test.
Arr.from5 1 2 3 4 5
|> Arr.takeWhen (\n -> n >= 3)
--> Arr.from3 3 4 5
--> : Arr (In Nat0 (Nat5Plus a_)) number_Remove values that satisfy a test.
Arr.from5 1 2 3 4 5
|> Arr.dropWhen (\n -> n < 3)
--> Arr.from3 3 4 5
--> : Arr (In Nat0 (Nat5Plus a_)) number_A certain number of elements from a direction.
Arr.from8 0 1 2 3 4 5 6 7
|> Arr.take nat7 FirstToLast
--> : Arr (In Nat3 Nat7) ...A certain number of elements from a direction.
Arr.from8 0 1 2 3 4 5 6 7
|> Arr.take nat3 nat3 LastToFirst
--> Arr.from3 5 6 7
Arr.from8 0 1 2 3 4 5 6 7
|> Arr.takeMax nat7 between3And7 FirstToLast
--> : Arr (In Nat3 Nat7) ...The first number is the maximum taken amount. The second number is the amount of taken elements.
Split the Arr into equal-sized chunks in a direction.
{ groups : the Arr divided into equal-sized Arrs
, less : values to one side which aren't enough
}
Arr.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 =
(+) ('a' |> Char.toCode)
>> Char.fromCodeval refers to Typed.val.
Reduce an Arr in a direction.
Arr.from5 "l" "i" "v" "e"
|> Arr.fold FirstToLast (++) ""
--> "live"
Arr.from5 "l" "i" "v" "e"
|> Arr.fold LastToFirst (++) ""
--> "evil"Convert 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 ]A fold where the initial result is the first value in the Arr, looking from a direction.
Arr.foldWith FirstToLast maximum
(Arr.from3 234 345 543)
--> 543
Arr.foldWith LastToFirst (++)
(Arr.from3 "m" "l" "e")
--> "elm"Often, calling map before foldWith is helpful.
Arr.map String.fromInt
>> Arr.foldWith FirstToLast (++)Flip the order of the elements.
Arr.from5 "l" "i" "v" "e"
|> Arr.reverse
--> Arr.from5 "e" "v" "i" "l"Resize an Arr in a direction, padding with a given value.
Arr.resize LastToFirst nat4 0
(Arr.from2 1 2)
--> Array.from4 0 0 1 2
Arr.resize LastToFirst nat2 0
(Array.from3 1 2 3)
--> Array.from2 2 3
Arr.resize FirstToLast nat4 0
(Array.from2 1 2)
--> Array.from4 1 2 0 0
Arr.resize FirstToLast nat2 0
(Array.from3 1 2 3)
--> Array.from2 1 2This is a quick way to gain some type-level knowledge about the length.
Take every Just value & drop every Nothing.
Arr.from3 (Just "This") Nothing (Just "fine")
|> Arr.values
--> Arr.from2 "this" "fine"
--> : Arr (In Nat0 (Nat3Plus a_)) StringOften, calling map before values is helpful. Many call this combination "filterMap".
Arr.from3 "1.2" "2" "hello"
|> Arr.map String.toInt
|> Arr.values
--> Arr.from1 2
--> : Arr (In Nat0 (Nat3Plus a_)) IntCombine the elements of 2 Arrs into new elements.
If one list is longer, its extra elements are not used.
teamLifes aBoard bBoard =
Arr.map2 (\a b -> a.lifes + b.lifes)
aBoard
bBoardThe length of all Arrs must be in the same range.
Arr's maximum length isn't known:Arr.map2 (\a b -> a.lifes + b.lifes)
(aBoard |> MinArr.value)
(bBoard |> MinArr.value)
aBoard : Arr (In Nat2 someMax) Field
bBoard : Arr (In Nat2 otherMax) FieldArr has a higher minimum length:Arr.map2 (\a b -> a.lifes + b.lifes)
(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
]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)
--> worksA Codec to serialize Arrs with a specific amount of elements.
import Serialize
-- we can't start if we have no worlds to choose from!
serializeGameRow :
Serialize.Codec
String
(Arr (Only Nat10) GameField)
serializeGameRow =
Arr.serialize nat10 serializeGameField
encode : Arr (Only Nat10) GameField -> Bytes
encode =
Serialize.encodeToBytes serializeGameRow
decode :
Bytes
->
Result
(Serialize.Error String)
(Arr (Only Nat10) GameField)
decode =
Serialize.decodeFromBytes serializeGameRow
An
Arrdescribes an array where you know more about the amount of elements.types
as argument types
as storage types
For example to store in your
Model