array package:harpie

Construct an array from a shape and a value without any shape validation.
>>> array [2,3] [0..5]
UnsafeArray [2,3] [0,1,2,3,4,5]
Construct an Array, throwing an exception on a bad shape.
>>> array [0..22] :: Array [2,3,4] Int
*** Exception: Shape Mismatch
...
Arrays with shape information and computations at a value-level.
A hyperrectangular (or multidimensional) array with a value-level shape.
>>> let a = array [2,3,4] [1..24] :: Array Int

>>> a
UnsafeArray [2,3,4] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
>>> pretty a
[[[1,2,3,4],
[5,6,7,8],
[9,10,11,12]],
[[13,14,15,16],
[17,18,19,20],
[21,22,23,24]]]
A hyperrectangular (or multidimensional) array with a type-level shape.
>>> array @[2,3,4] @Int [1..24]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]

>>> array [1..24] :: Array '[2,3,4] Int
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]

>>> pretty (array @[2,3,4] @Int [1..24])
[[[1,2,3,4],
[5,6,7,8],
[9,10,11,12]],
[[13,14,15,16],
[17,18,19,20],
[21,22,23,24]]]
>>> array [1,2,3] :: Array '[2,2] Int
*** Exception: Shape Mismatch
...
In many situations, the use of TypeApplication can lead to a clean coding style.
>>> array @[2,3] @Int [1..6]
[1,2,3,4,5,6]
The main computational entry and exit points are often via index and tabulate with arrays indexed by Fins:
>>> index a (S.UnsafeFins [1,2,3])
23
>>> :t tabulate id :: Array [2,3] (Fins [2,3])
tabulate id :: Array [2,3] (Fins [2,3])
:: Array [2, 3] (Fins [2, 3])

>>> pretty (tabulate id :: Array [2,3] (Fins [2,3]))
[[[0,0],[0,1],[0,2]],
[[1,0],[1,1],[1,2]]]
Conversion to and from an Array Note that conversion of an Array to a FromArray likely drops shape information, so that:
arrayAs . asArray == flat
asArray . arrayAs == id
>>> asArray ([0..5::Int])
UnsafeArray [6] [0,1,2,3,4,5]
>>> arrayAs (range [2,3]) :: [Int]
[0,1,2,3,4,5]
Construct an Array, checking shape.
>>> safeArray [2,3,4] [0..23] == Just a
True
Sigma type for an Array A fixed Array where shape was unknown at runtime. The library design encourages the use of value-level shape arrays (in Harpie.Array) via toDynamic in preference to dependent-type styles of coding. In particular, no attempt has been made to prove to the compiler that a particular Shape (resulting from any of the supplied functions) exists. Life is short.
> P.take 4 <$> sample' arbitrary :: IO [SomeArray Int]
> [SomeArray SNats @'[] [0],SomeArray SNats @'[0] [],SomeArray SNats @[1, 1] [1],SomeArray SNats @[5, 1, 4] [2,1,0,2,-6,0,5,6,-1,-4,0,5,-1,6,4,-6,1,0,3,-1]]
Construct an Array, checking shape.
>>> (safeArray [0..23] :: Maybe (Array [2,3,4] Int)) == Just a
True
Construct a SomeArray
Construct an array without shape validation.
>>> unsafeArray [0..4] :: Array [2,3] Int
[0,1,2,3,4]