harpie
Safe HaskellNone
LanguageGHC2024

Harpie.Array.Generic

Description

Arrays with shape information and computations at a value-level.

This is the generic core: the backing vector family is a parameter v. Concrete modules (Array, Storable, Unboxed) provide type aliases for the common vector families.

Synopsis

Usage

Several names used in harpie conflict with Prelude:

>>> import Prelude hiding (cycle, repeat, take, drop, zipWith, length)

In general, Array functionality is contained in Harpie.Array and shape functionality is contained in Harpie.Shape. These two modules also have name clashes and at least one needs to be qualified:

>>> import Harpie.Array.Generic as A
>>> import Harpie.Shape qualified as S

prettyprinter is used to prettily render arrays to better visualise shape.

>>> import Prettyprinter hiding (dot,fill)

Examples of arrays:

An array with no dimensions (a scalar).

>>> s = 1 :: Array Vector Int
>>> s
UnsafeArray [] [1]
>>> shape s
[]
>>> pretty s
1

A single-dimension array (a vector).

>>> let v = range [3]
>>> pretty v
[0,1,2]

A two-dimensional array (a matrix).

>>> let m = range [2,3]
>>> pretty m
[[0,1,2],
 [3,4,5]]

An n-dimensional array (n should be finite).

>>> a = range [2,3,4]
>>> a
UnsafeArray [2,3,4] [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]
>>> pretty a
[[[0,1,2,3],
  [4,5,6,7],
  [8,9,10,11]],
 [[12,13,14,15],
  [16,17,18,19],
  [20,21,22,23]]]

Harpie Arrays

data Array (v :: k -> Type) (a :: k) Source #

A hyperrectangular (or multidimensional) array with a value-level shape.

>>> let a = array [2,3,4] [1..24] :: Array Vector 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]]]

Constructors

UnsafeArray !(Vector Int) !(Vector Int) !(v a) 

Instances

Instances details
Storable a => FromArray (Array a) a Source # 
Instance details

Defined in Harpie.Array.Storable

Methods

asArray :: Array a -> Array a Source #

arrayAs :: Array a -> Array a Source #

Storable a => FromVector (Array a) a Source # 
Instance details

Defined in Harpie.Array.Storable

Methods

asVector :: Array a -> Vector a Source #

vectorAs :: Vector a -> Array a Source #

Unbox a => FromArray (Array a) a Source # 
Instance details

Defined in Harpie.Array.Unboxed

Methods

asArray :: Array a -> Array a Source #

arrayAs :: Array a -> Array a Source #

Unbox a => FromVector (Array a) a Source # 
Instance details

Defined in Harpie.Array.Unboxed

Methods

asVector :: Array a -> Vector a Source #

vectorAs :: Vector a -> Array a Source #

Eq (v a) => Eq (Array v a) Source # 
Instance details

Defined in Harpie.Array.Generic

Methods

(==) :: Array v a -> Array v a -> Bool #

(/=) :: Array v a -> Array v a -> Bool #

Ord (v a) => Ord (Array v a) Source # 
Instance details

Defined in Harpie.Array.Generic

Methods

compare :: Array v a -> Array v a -> Ordering #

(<) :: Array v a -> Array v a -> Bool #

(<=) :: Array v a -> Array v a -> Bool #

(>) :: Array v a -> Array v a -> Bool #

(>=) :: Array v a -> Array v a -> Bool #

max :: Array v a -> Array v a -> Array v a #

min :: Array v a -> Array v a -> Array v a #

Generic (Array v a) Source # 
Instance details

Defined in Harpie.Array.Generic

Associated Types

type Rep (Array v a) 
Instance details

Defined in Harpie.Array.Generic

Methods

from :: Array v a -> Rep (Array v a) x #

to :: Rep (Array v a) x -> Array v a #

(Num a, Vector v a) => Num (Array v a) Source # 
Instance details

Defined in Harpie.Array.Generic

Methods

(+) :: Array v a -> Array v a -> Array v a #

(-) :: Array v a -> Array v a -> Array v a #

(*) :: Array v a -> Array v a -> Array v a #

negate :: Array v a -> Array v a #

abs :: Array v a -> Array v a #

signum :: Array v a -> Array v a #

fromInteger :: Integer -> Array v a #

Show (v a) => Show (Array v a) Source # 
Instance details

Defined in Harpie.Array.Generic

Methods

showsPrec :: Int -> Array v a -> ShowS #

show :: Array v a -> String #

showList :: [Array v a] -> ShowS #

(Show a, Show (v a), Vector v a, Vector v (Array v a)) => Pretty (Array v a) Source # 
Instance details

Defined in Harpie.Array.Generic

Methods

pretty :: Array v a -> Doc ann #

prettyList :: [Array v a] -> Doc ann #

type Rep (Array v a) Source # 
Instance details

Defined in Harpie.Array.Generic

array :: forall (v :: Type -> Type) a. Vector v a => [Int] -> [a] -> Array v a Source #

Construct an array from a shape and a list of elements.

>>> array [2,3] [0..5]
UnsafeArray [2,3] [0,1,2,3,4,5]

(><) :: forall (v :: Type -> Type) a. Vector v a => [Int] -> [a] -> Array v a infixl 4 Source #

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.

>>> pretty $ [2,3] >< [0..5]
[[0,1,2],
 [3,4,5]]

validate :: forall (v :: Type -> Type) a. Vector v a => Array v a -> Bool Source #

Validate the size and shape of an array.

>>> validate (array [2,3,4] [1..23] :: Array Vector Int)
False

safeArray :: forall (v :: Type -> Type) a. Vector v a => [Int] -> [a] -> Maybe (Array v a) Source #

Construct an Array, checking shape.

>>> safeArray [2,3,4] [0..23] == Just a
True

unsafeArray :: forall {k} v (a :: k). Vector Int -> v a -> Array v a Source #

Internal smart constructor: precomputes strides for O(1) zero-allocation indexing.

unsafeArrayL :: forall {k} v (a :: k). [Int] -> v a -> Array v a Source #

Internal smart constructor from a list shape.

unsafeModifyShape :: forall {k} (v :: k -> Type) (a :: k). (Vector Int -> Vector Int) -> Array v a -> Array v a Source #

Unsafely modify an array shape.

>>> unsafeModifyShape (VU.map (+1)) (array [2,3] [0..5])
UnsafeArray [3,4] [0,1,2,3,4,5]

unsafeModifyVector :: forall {k1} {k2} v (a :: k1) v' (b :: k2). (v a -> v' b) -> Array v a -> Array v' b Source #

Unsafely modify an array vector.

>>> unsafeModifyVector (VG.map (+1)) (array [2,3] [0..5])
UnsafeArray [2,3] [1,2,3,4,5,6]

Dimensions

type Dim = Int Source #

Representation of an index into a shape (an [Int]). The index is a dimension of the shape.

type Dims = [Int] Source #

Representation of indexes into a shape (an [Int]). The indexes are dimensions of the shape.

Conversion

asVector :: forall {k} v (a :: k). Array v a -> v a Source #

Convert an array to its underlying vector. Drops shape information.

asVector . arrayV [size a] . asVector == a
>>> asVector (range [2,3])
[0,1,2,3,4,5]

arrayV :: forall {k} v (a :: k). [Int] -> v a -> Array v a Source #

Construct an array from a shape and an already-correctly-sized vector.

Shape Access

shape :: forall {k} (v :: k -> Type) (a :: k). Array v a -> Vector Int Source #

shape of an Array

>>> shape a
[2,3,4]

rank :: forall {k} (v :: k -> Type) (a :: k). Array v a -> Int Source #

rank of an Array

>>> rank a
3

size :: forall {k} (v :: k -> Type) (a :: k). Array v a -> Int Source #

size of an Array, which is the total number of elements, if the Array Vector is valid.

>>> size a
24

length :: forall {k} (v :: k -> Type) (a :: k). Array v a -> Int Source #

Number of rows (first dimension size) in an Array. As a convention, a scalar value is still a single row.

>>> length a
2
>>> length (toScalar 0)
1

isNull :: forall {k} (v :: k -> Type) (a :: k). Array v a -> Bool Source #

Is the Array Vector empty (has zero number of elements).

>>> isNull ([2,0] >< [] :: Array Vector ())
True
>>> isNull ([] >< [4] :: Array Vector Int)
False

Indexing

index :: forall (v :: Type -> Type) a. Vector v a => Array v a -> [Int] -> a Source #

Extract an element at an index, unsafely.

>>> index a [1,2,3]
23

(!) :: forall (v :: Type -> Type) a. Vector v a => Array v a -> [Int] -> a infixl 9 Source #

Extract an element at an index, unsafely.

>>> a ! [1,2,3]
23

(!?) :: forall (v :: Type -> Type) a. Vector v a => Array v a -> [Int] -> Maybe a Source #

Extract an element at an index, safely.

>>> a !? [1,2,3]
Just 23
>>> a !? [2,3,1]
Nothing

tabulate :: forall (v :: Type -> Type) a. Vector v a => [Int] -> ([Int] -> a) -> Array v a Source #

Tabulate an array supplying a shape and a tabulation function.

>>> tabulate [2,3,4] (S.flatten (VU.fromList [2,3,4]) . VU.fromList) == a
True

backpermute :: forall (v :: Type -> Type) a. Vector v a => (Vector Int -> Vector Int) -> (Vector Int -> Vector Int) -> Array v a -> Array v a Source #

backpermute is a tabulation where the contents of an array do not need to be accessed, and is thus a fulcrum for leveraging laziness and fusion via the rule:

backpermute f g (backpermute f' g' a) == backpermute (f . f') (g . g') a

Many functions in this module are examples of backpermute usage.

>>> pretty $ backpermute VU.reverse VU.reverse a
[[[0,12],
  [4,16],
  [8,20]],
 [[1,13],
  [5,17],
  [9,21]],
 [[2,14],
  [6,18],
  [10,22]],
 [[3,15],
  [7,19],
  [11,23]]]

Scalars

fromScalar :: forall (v :: Type -> Type) a. Vector v a => Array v a -> a Source #

Unwrap a scalar.

>>> let s = array [] [3] :: Array Vector Int
>>> fromScalar s
3

toScalar :: forall (v :: Type -> Type) a. Vector v a => a -> Array v a Source #

Wrap a scalar.

>>> :t toScalar 2
toScalar 2 :: Num a => Array Vector a

isScalar :: forall {k} (v :: k -> Type) (a :: k). Array v a -> Bool Source #

Is an array a Scalar?

>>> isScalar (toScalar (2::Int))
True

asSingleton :: forall {k} (v :: k -> Type) (a :: k). Array v a -> Array v a Source #

Convert a scalar to being a dimensioned array. Do nothing if not a scalar.

>>> asSingleton (toScalar 4)
UnsafeArray [1] [4]

asScalar :: forall {k} (v :: k -> Type) (a :: k). Array v a -> Array v a Source #

Convert an array with shape [1] to being a scalar (Do nothing if not a shape [1] array).

>>> asScalar (singleton 3)
UnsafeArray [] [3]

Array v Creation

empty :: forall (v :: Type -> Type) a. Vector v a => Array v a Source #

An array with no elements.

>>> empty
UnsafeArray [0] []

range :: forall (v :: Type -> Type). Vector v Int => [Int] -> Array v Int Source #

An enumeration of row-major or lexicographic order.

>>> pretty $ range [2,3]
[[0,1,2],
 [3,4,5]]

corange :: forall (v :: Type -> Type). Vector v Int => [Int] -> Array v Int Source #

An enumeration of col-major or colexicographic order.

>>> pretty (corange [2,3,4])
[[[0,6,12,18],
  [2,8,14,20],
  [4,10,16,22]],
 [[1,7,13,19],
  [3,9,15,21],
  [5,11,17,23]]]

indices :: forall (v :: Type -> Type). Vector v [Int] => [Int] -> Array v [Int] Source #

Indices of an array shape.

>>> pretty $ indices [3,3]
[[[0,0],[0,1],[0,2]],
 [[1,0],[1,1],[1,2]],
 [[2,0],[2,1],[2,2]]]

ident :: forall a (v :: Type -> Type). (Additive a, Multiplicative a, Vector v a) => [Int] -> Array v a Source #

The identity array.

>>> pretty $ ident [3,3]
[[1,0,0],
 [0,1,0],
 [0,0,1]]

konst :: forall (v :: Type -> Type) a. Vector v a => [Int] -> a -> Array v a Source #

Create an array composed of a single value.

>>> pretty $ konst [3,2] 1
[[1,1],
 [1,1],
 [1,1]]

singleton :: forall (v :: Type -> Type) a. Vector v a => a -> Array v a Source #

Create an array of shape [1].

>>> pretty $ singleton 1
[1]
>>> singleton 3 == toScalar 3
False
>>> asVector (singleton 3) == asVector (toScalar 3)
True

diag :: forall (v :: Type -> Type) a. Vector v a => Array v a -> Array v a Source #

Extract the diagonal of an array.

>>> pretty $ diag (ident [3,3])
[1,1,1]

undiag :: forall (v :: Type -> Type) a. (Vector v a, Additive a) => Array v a -> Array v a Source #

Expand the array to form a diagonal array.

>>> pretty $ undiag (range [3])
[[0,0,0],
 [0,1,0],
 [0,0,2]]

Element-level functions

fmapA :: forall (v :: Type -> Type) a b. (Vector v a, Vector v b) => (a -> b) -> Array v a -> Array v b Source #

Functor-like map with an explicit vector constraint.

foldrA :: forall (v :: Type -> Type) a b. Vector v a => (a -> b -> b) -> b -> Array v a -> b Source #

Foldable-like fold with an explicit vector constraint.

toListA :: forall (v :: Type -> Type) a. Vector v a => Array v a -> [a] Source #

Convert an array to a list.

zipWith :: forall (v :: Type -> Type) a b c. (Vector v a, Vector v b, Vector v c) => (a -> b -> c) -> Array v a -> Array v b -> Array v c Source #

Zip two arrays at an element level.

>>> zipWith (-) v v
UnsafeArray [3] [0,0,0]

zipWithSafe :: forall (v :: Type -> Type) a b c. (Vector v a, Vector v b, Vector v c) => (a -> b -> c) -> Array v a -> Array v b -> Maybe (Array v c) Source #

Zip two arrays at an element level, checking for shape consistency.

>>> zipWithSafe (-) (range [3]) (range [4])
Nothing

modify :: forall (v :: Type -> Type) a. Vector v a => [Int] -> (a -> a) -> Array v a -> Array v a Source #

Modify a single value at an index.

>>> pretty $ modify [0,0] (const 100) (range [3,2])
[[100,1],
 [2,3],
 [4,5]]

imap :: forall (v :: Type -> Type) a b. (Vector v a, Vector v b, Vector v [Int]) => ([Int] -> a -> b) -> Array v a -> Array v b Source #

Maps an index function at element-level.

>>> pretty $ imap (\xs x -> x - sum xs) a
[[[0,0,0,0],
  [3,3,3,3],
  [6,6,6,6]],
 [[11,11,11,11],
  [14,14,14,14],
  [17,17,17,17]]]

Function generalisers

rowWise :: forall {k} x (v :: k -> Type) (a :: k). (Dims -> [x] -> Array v a -> Array v a) -> [x] -> Array v a -> Array v a Source #

With a function that takes dimensions and (type-level) parameters, apply the parameters to the initial dimensions. ie

rowWise f xs = f [0..] xs
>>> rowWise indexes [1,0] a
UnsafeArray [4] [12,13,14,15]

colWise :: forall {k} x (v :: k -> Type) (a :: k). (Dims -> [x] -> Array v a -> Array v a) -> [x] -> Array v a -> Array v a Source #

With a function that takes dimensions and (type-level) parameters, apply the parameters to the the last dimensions. ie

colWise f xs = f (List.reverse [0 .. (rank a - 1)]) xs
>>> colWise indexes [1,0] a
UnsafeArray [2] [1,13]

dimsWise :: forall {k} x (v :: k -> Type) (a :: k). (Dim -> x -> Array v a -> Array v a) -> Dims -> [x] -> Array v a -> Array v a Source #

With a function that takes a dimension and a parameter, fold dimensions and parameters using the function.

>>> dimsWise take [0,2] [1,2] a
UnsafeArray [1,3,2] [0,1,4,5,8,9]

Single-dimension functions

take :: forall (v :: Type -> Type) a. Vector v a => Dim -> Int -> Array v a -> Array v a Source #

Take the top-most elements across the specified dimension. Negative values take the bottom-most. No index check is performed.

take d x == takes [(d,x)]
>>> pretty $ take 2 1 a
[[[0],
  [4],
  [8]],
 [[12],
  [16],
  [20]]]
>>> pretty $ take 2 (-1) a
[[[3],
  [7],
  [11]],
 [[15],
  [19],
  [23]]]

drop :: forall (v :: Type -> Type) a. Vector v a => Dim -> Int -> Array v a -> Array v a Source #

Drop the top-most elements across the specified dimension. Negative values take the bottom-most.

>>> pretty $ drop 2 1 a
[[[1,2,3],
  [5,6,7],
  [9,10,11]],
 [[13,14,15],
  [17,18,19],
  [21,22,23]]]
>>> pretty $ drop 2 (-1) a
[[[0,1,2],
  [4,5,6],
  [8,9,10]],
 [[12,13,14],
  [16,17,18],
  [20,21,22]]]

select :: forall (v :: Type -> Type) a. Vector v a => Dim -> Int -> Array v a -> Array v a Source #

Select an index along a dimension.

>>> let s = select 2 3 a
>>> pretty s
[[3,7,11],
 [15,19,23]]

insert :: forall (v :: Type -> Type) a. Vector v a => Dim -> Int -> Array v a -> Array v a -> Array v a Source #

Insert along a dimension at a position.

>>> pretty $ insert 2 0 a (konst [2,3] 0)
[[[0,0,1,2,3],
  [0,4,5,6,7],
  [0,8,9,10,11]],
 [[0,12,13,14,15],
  [0,16,17,18,19],
  [0,20,21,22,23]]]
>>> insert 0 0 (toScalar 1) (toScalar 2)
UnsafeArray [2] [2,1]

delete :: forall (v :: Type -> Type) a. Vector v a => Dim -> Int -> Array v a -> Array v a Source #

Delete along a dimension at a position.

>>> pretty $ delete 2 0 a
[[[1,2,3],
  [5,6,7],
  [9,10,11]],
 [[13,14,15],
  [17,18,19],
  [21,22,23]]]

append :: forall (v :: Type -> Type) a. Vector v a => Dim -> Array v a -> Array v a -> Array v a Source #

Insert along a dimension at the end.

>>> pretty $ append 2 a (konst [2,3] 0)
[[[0,1,2,3,0],
  [4,5,6,7,0],
  [8,9,10,11,0]],
 [[12,13,14,15,0],
  [16,17,18,19,0],
  [20,21,22,23,0]]]

prepend :: forall (v :: Type -> Type) a. Vector v a => Dim -> Array v a -> Array v a -> Array v a Source #

Insert along a dimension at the beginning.

>>> pretty $ prepend 2 (konst [2,3] 0) a
[[[0,0,1,2,3],
  [0,4,5,6,7],
  [0,8,9,10,11]],
 [[0,12,13,14,15],
  [0,16,17,18,19],
  [0,20,21,22,23]]]

concatenate :: forall (v :: Type -> Type) a. Vector v a => Dim -> Array v a -> Array v a -> Array v a Source #

Concatenate along a dimension.

>>> shape $ concatenate 1 a a
[2,6,4]
>>> concatenate 0 (toScalar 1) (toScalar 2)
UnsafeArray [2] [1,2]
>>> concatenate 0 (toScalar 0) (asArray [1..3])
UnsafeArray [4] [0,1,2,3]

couple :: forall (v :: Type -> Type) a. Vector v a => Int -> Array v a -> Array v a -> Array v a Source #

Combine two arrays as a new dimension of a new array.

>>> pretty $ couple 0 (asArray [1,2,3]) (asArray [4,5,6::Int])
[[1,2,3],
 [4,5,6]]

slice :: forall (v :: Type -> Type) a. Vector v a => Dim -> Int -> Int -> Array v a -> Array v a Source #

Slice along a dimension with the supplied offset & length.

>>> let s = slice 2 1 2 a
>>> pretty s
[[[1,2],
  [5,6],
  [9,10]],
 [[13,14],
  [17,18],
  [21,22]]]

rotate :: forall (v :: Type -> Type) a. Vector v a => Dim -> Int -> Array v a -> Array v a Source #

Rotate an array along a dimension.

>>> pretty $ rotate 1 2 a
[[[8,9,10,11],
  [0,1,2,3],
  [4,5,6,7]],
 [[20,21,22,23],
  [12,13,14,15],
  [16,17,18,19]]]

Multi-dimension functions

takes :: forall (v :: Type -> Type) a. Vector v a => Dims -> [Int] -> Array v a -> Array v a Source #

Takes the top-most elements across the supplied dimension,n tuples. Negative values take the bottom-most.

takes == dimsWise take
>>> pretty $ takes [0,2] [1,-3] a
[[[1,2,3],
  [5,6,7],
  [9,10,11]]]

drops :: forall (v :: Type -> Type) a. Vector v a => Dims -> [Int] -> Array v a -> Array v a Source #

Drops the top-most elements. Negative values drop the bottom-most.

>>> pretty $ drops [0,1,2] [1,2,-3] a
[[[20]]]

indexes :: forall (v :: Type -> Type) a. Vector v a => Dims -> [Int] -> Array v a -> Array v a Source #

Select by dimensions and indexes.

>>> let s = indexes [0,1] [1,1] a
>>> pretty s
[16,17,18,19]

slices :: forall (v :: Type -> Type) a. Vector v a => Dims -> [Int] -> [Int] -> Array v a -> Array v a Source #

Slice along dimensions with the supplied offsets and lengths.

>>> let s = slices [2,0] [1,1] [2,1] a
>>> pretty s
[[[13,14],
  [17,18],
  [21,22]]]

heads :: forall (v :: Type -> Type) a. Vector v a => Dims -> Array v a -> Array v a Source #

Select the first element along the supplied dimensions.

>>> pretty $ heads [0,2] a
[0,4,8]

lasts :: forall (v :: Type -> Type) a. Vector v a => Dims -> Array v a -> Array v a Source #

Select the last element along the supplied dimensions.

>>> pretty $ lasts [0,2] a
[15,19,23]

tails :: forall (v :: Type -> Type) a. Vector v a => Dims -> Array v a -> Array v a Source #

Select the tail elements along the supplied dimensions.

>>> pretty $ tails [0,2] a
[[[13,14,15],
  [17,18,19],
  [21,22,23]]]

inits :: forall (v :: Type -> Type) a. Vector v a => Dims -> Array v a -> Array v a Source #

Select the init elements along the supplied dimensions.

>>> pretty $ inits [0,2] a
[[[0,1,2],
  [4,5,6],
  [8,9,10]]]

Function application

extracts :: forall (v :: Type -> Type) a. (Vector v (Array v a), Vector v a) => Dims -> Array v a -> Array v (Array v a) Source #

Extracts dimensions to an outer layer.

>>> pretty $ fmapA shape (extracts [0] a)
[[3,4],[3,4]]

reduces :: forall (v :: Type -> Type) a b. (Vector v a, Vector v b, Vector v (Array v a)) => Dims -> (Array v a -> b) -> Array v a -> Array v b Source #

Reduce along specified dimensions, using the supplied fold.

>>> pretty $ reduces [0] sumA a
[66,210]
>>> pretty $ reduces [0,2] sumA a
[[12,15,18,21],
 [48,51,54,57]]

joins :: forall (v :: Type -> Type) a. (Vector v (Array v a), Vector v a) => Dims -> Array v (Array v a) -> Array v a Source #

Join inner and outer dimension layers by supplied dimensions. No checks on shape.

>>> let e = extracts [1,0] a
>>> let j = joins [1,0] e
>>> a == j
True

joinsSafe :: forall (v :: Type -> Type) a. (Vector v (Array v a), Vector v a, Vector v (Vector Int)) => Dims -> Array v (Array v a) -> Maybe (Array v a) Source #

Join inner and outer dimension layers by supplied dimensions. Check inner layer shape.

>>> let e = extracts [1,0] a
>>> (Just j) = joinsSafe [1,0] e
>>> a == j
True

join :: forall (v :: Type -> Type) a. (Vector v (Array v a), Vector v a) => Array v (Array v a) -> Array v a Source #

Join inner and outer dimension layers in outer dimension order.

>>> a == join (extracts [0,1] a)
True

joinSafe :: forall (v :: Type -> Type) a. (Vector v (Array v a), Vector v a, Vector v (Vector Int)) => Array v (Array v a) -> Maybe (Array v a) Source #

Join inner and outer dimension layers in outer dimension order, checking for consistent inner dimension shape.

>>> joinSafe (extracts [0,1] a)
Just (UnsafeArray [2,3,4] [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23])

traverses :: forall (v :: Type -> Type) a b f. (Vector v a, Vector v b, Vector v (Array v a), Vector v (Array v b), Vector v (f b), Vector v (f (Array v b)), Applicative f) => Dims -> (a -> f b) -> Array v a -> f (Array v b) Source #

Traverse along specified dimensions.

traverses [1] print (range [2,3]) 0 3 1 4 2 5 UnsafeArray [2,3] [(),(),(),(),(),()]

maps :: forall (v :: Type -> Type) a b. (Vector v a, Vector v b, Vector v (Array v a), Vector v (Array v b)) => Dims -> (Array v a -> Array v b) -> Array v a -> Array v b Source #

Maps a function along specified dimensions.

>>> pretty $ maps [1] transpose a
[[[0,12],
  [4,16],
  [8,20]],
 [[1,13],
  [5,17],
  [9,21]],
 [[2,14],
  [6,18],
  [10,22]],
 [[3,15],
  [7,19],
  [11,23]]]

filters :: forall (v :: Type -> Type) a. (Vector v a, Vector v (Array v a)) => Dims -> (Array v a -> Bool) -> Array v a -> Array v a Source #

Filters along specified dimensions (which are flattened).

>>> pretty $ filters [0,1] (anyA ((==0) . (`mod` 7))) a
[[0,1,2,3],
 [4,5,6,7],
 [12,13,14,15],
 [20,21,22,23]]

zips :: forall (v :: Type -> Type) a b c. (Vector v a, Vector v b, Vector v c, Vector v (Array v a), Vector v (Array v b), Vector v (Array v c)) => Dims -> (Array v a -> Array v b -> Array v c) -> Array v a -> Array v b -> Array v c Source #

Zips two arrays with a function along specified dimensions.

>>> pretty $ zips [0,1] (zipWith (,)) a (reverses [0] a)
[[[(0,12),(1,13),(2,14),(3,15)],
  [(4,16),(5,17),(6,18),(7,19)],
  [(8,20),(9,21),(10,22),(11,23)]],
 [[(12,0),(13,1),(14,2),(15,3)],
  [(16,4),(17,5),(18,6),(19,7)],
  [(20,8),(21,9),(22,10),(23,11)]]]

zipsSafe :: forall (v :: Type -> Type) a b c. (Vector v a, Vector v b, Vector v c, Vector v (Array v a), Vector v (Array v b), Vector v (Array v c)) => Dims -> (Array v a -> Array v b -> Array v c) -> Array v a -> Array v b -> Maybe (Array v c) Source #

Zips two arrays with a function along specified dimensions, checking shapes.

>>> zipsSafe [0] (zipWith (,)) (asArray [1::Int]) (asArray [1,2::Int])
Nothing

modifies :: forall (v :: Type -> Type) a. (Vector v a, Vector v (Array v a)) => (Array v a -> Array v a) -> Dims -> [Int] -> Array v a -> Array v a Source #

Modify using the supplied function along dimensions & positions.

>>> pretty $ modifies (fmapA (100+)) [2] [0] a
[[[100,1,2,3],
  [104,5,6,7],
  [108,9,10,11]],
 [[112,13,14,15],
  [116,17,18,19],
  [120,21,22,23]]]

diffs :: forall (v :: Type -> Type) a b. (Vector v a, Vector v b, Vector v (Array v a), Vector v (Array v b)) => Dims -> [Int] -> (Array v a -> Array v a -> Array v b) -> Array v a -> Array v b Source #

Apply a binary function between successive slices, across dimensions and lags.

>>> pretty $ diffs [1] [1] (zipWith (-)) a
[[[4,4,4,4],
  [4,4,4,4]],
 [[4,4,4,4],
  [4,4,4,4]]]

Array v expansion & contraction

expand :: forall (v :: Type -> Type) a b c. (Vector v a, Vector v b, Vector v c) => (a -> b -> c) -> Array v a -> Array v b -> Array v c Source #

Product two arrays using the supplied binary function.

For context, if the function is multiply, and the arrays are tensors, then this can be interpreted as a tensor product. The concept of a tensor product is a dense crossroad, and a complete treatment is elsewhere. To quote the wiki article:

... the tensor product can be extended to other categories of mathematical objects in addition to vector spaces, such as to matrices, tensors, algebras, topological vector spaces, and modules. In each such case the tensor product is characterized by a similar universal property: it is the freest bilinear operation. The general concept of a "tensor product" is captured by monoidal categories; that is, the class of all things that have a tensor product is a monoidal category.

>>> x = array [3] [1,2,3]
>>> pretty $ expand (*) x x
[[1,2,3],
 [2,4,6],
 [3,6,9]]

Alternatively, expand can be understood as representing the permutation of element pairs of two arrays, so like the Applicative List instance.

>>> i2 = indices [2,2]
>>> pretty $ expand (,) i2 i2
[[[[([0,0],[0,0]),([0,0],[0,1])],
   [([0,0],[1,0]),([0,0],[1,1])]],
  [[([0,1],[0,0]),([0,1],[0,1])],
   [([0,1],[1,0]),([0,1],[1,1])]]],
 [[[([1,0],[0,0]),([1,0],[0,1])],
   [([1,0],[1,0]),([1,0],[1,1])]],
  [[([1,1],[0,0]),([1,1],[0,1])],
   [([1,1],[1,0]),([1,1],[1,1])]]]]

coexpand :: forall (v :: Type -> Type) a b c. (Vector v a, Vector v b, Vector v c) => (a -> b -> c) -> Array v a -> Array v b -> Array v c Source #

Like expand, but permutes the first array first, rather than the second.

>>> pretty $ expand (,) v (fmapA (+3) v)
[[(0,3),(0,4),(0,5)],
 [(1,3),(1,4),(1,5)],
 [(2,3),(2,4),(2,5)]]
>>> pretty $ coexpand (,) v (fmapA (+3) v)
[[(0,3),(1,3),(2,3)],
 [(0,4),(1,4),(2,4)],
 [(0,5),(1,5),(2,5)]]

The output shape is shape b ++ shape a, so the first array's axes occupy the suffix of the product shape rather than the prefix. Equivalently, it is expand followed by the block-swap permutation that exchanges the two operand shapes.

contract :: forall (v :: Type -> Type) a b. (Vector v a, Vector v b, Vector v (Array v a)) => Dims -> (Array v a -> b) -> Array v a -> Array v b Source #

Contract an array by applying the supplied (folding) function on diagonal elements of the dimensions.

This generalises a tensor contraction by allowing the number of contracting diagonals to be other than 2.

>>> pretty $ contract [1,2] sumA (expand (*) m (transpose m))
[[5,14],
 [14,50]]

prod :: forall (v :: Type -> Type) a b c d. (Vector v a, Vector v b, Vector v c, Vector v d) => Dims -> Dims -> (Array v c -> d) -> (a -> b -> c) -> Array v a -> Array v b -> Array v d Source #

Product two arrays using the supplied function and then contract the result using the supplied matching dimensions and function.

>>> pretty $ prod [1] [0] sumA (*) (range [2,3]) (range [3,2])
[[10,13],
 [28,40]]

With full laziness, this computation would be equivalent to:

f . diag <$> extracts ds' (expand g a b)

dot :: forall (v :: Type -> Type) a b c d. (Vector v a, Vector v b, Vector v c, Vector v d, Vector v (Array v c)) => (Array v c -> d) -> (a -> b -> c) -> Array v a -> Array v b -> Array v d Source #

A generalisation of a dot operation, which is a multiplicative expansion of two arrays and sum contraction along the middle two dimensions.

matrix multiplication

>>> pretty $ dot sumA (*) m (transpose m)
[[5,14],
 [14,50]]

inner product

>>> pretty $ dot sumA (*) v v
5

matrix-vector multiplication Note that an Array Vector with shape [3] is neither a row vector nor column vector.

>>> pretty $ dot sumA (*) v (transpose m)
[5,14]
>>> pretty $ dot sumA (*) m v
[5,14]

mult :: forall (v :: Type -> Type) a. (Vector v a, Additive a, Multiplicative a) => Array v a -> Array v a -> Array v a Source #

Array Vector multiplication.

matrix multiplication

>>> pretty $ mult m (transpose m)
[[5,14],
 [14,50]]

inner product

>>> pretty $ mult v v
5

matrix-vector multiplication

>>> pretty $ mult v (transpose m)
[5,14]
>>> pretty $ mult m v
[5,14]

windows :: forall (v :: Type -> Type) a. Vector v a => [Int] -> Array v a -> Array v a Source #

windows xs are xs-sized windows of an array

>>> shape $ windows [2,2] (range [4,3,2])
[3,2,2,2,2]

Search

find :: forall (v :: Type -> Type) a. (Eq (v a), Vector v Bool, Vector v a, Vector v (Array v a)) => Array v a -> Array v a -> Array v Bool Source #

Find the starting positions of occurences of one array in another.

>>> a = cycle [4,4] (range [3]) :: Array Vector Int
>>> i = array [2,2] [1,2,2,0] :: Array Vector Int
>>> pretty $ find i a
[[False,True,False],
 [True,False,False],
 [False,False,True]]

findNoOverlap :: forall (v :: Type -> Type) a. (Eq (v a), Vector v Bool, Vector v a, Vector v (Array v a)) => Array v a -> Array v a -> Array v Bool Source #

Find the ending positions of one array in another except where the array overlaps with another copy.

>>> a = konst [5,5] 1 :: Array Vector Int
>>> i = konst [2,2] 1 :: Array Vector Int
>>> pretty $ findNoOverlap i a
[[True,False,True,False],
 [False,False,False,False],
 [True,False,True,False],
 [False,False,False,False]]

findIndices :: forall (v :: Type -> Type) a. (Eq (v a), Vector v [Int], Vector v a, Vector v Bool, Vector v ([Int], Bool), Vector v (Array v a)) => Array v a -> Array v a -> Array v [Int] Source #

Find the indices of the starting location of one array in another.

>>> b = cycle [4,4] (range [3]) :: Array Vector Int
>>> i = array [2,2] [1,2,2,0] :: Array Vector Int
>>> pretty $ findIndices i b
[[0,1],[1,0],[2,2]]

isPrefixOf :: forall (v :: Type -> Type) a. (Eq (v a), Vector v a) => Array v a -> Array v a -> Bool Source #

Check if the first array is a prefix of the second

>>> isPrefixOf (array [2,2] [0,1,4,5]) a
True

isSuffixOf :: forall (v :: Type -> Type) a. (Eq (v a), Vector v a) => Array v a -> Array v a -> Bool Source #

Check if the first array is a suffix of the second

>>> isSuffixOf (array [2,2] [18,19,22,23]) a
True

isInfixOf :: forall (v :: Type -> Type) a. (Eq (v a), Vector v a, Vector v Bool, Vector v (Array v a)) => Array v a -> Array v a -> Bool Source #

Check if the first array is an infix of the second

>>> isInfixOf (array [2,2] [18,19,22,23]) a
True

Shape manipulations

fill :: forall (v :: Type -> Type) a. Vector v a => a -> Array v a -> Array v a Source #

Fill an array with the supplied value without regard to the original shape or cut the array values to match array size.

validate (def x a) == True
>>> pretty $ fill 0 (array [3] [])
[0,0,0]
>>> pretty $ fill 0 (array [3] [1..4])
[1,2,3]

cut :: forall (v :: Type -> Type) a. Vector v a => [Int] -> Array v a -> Array v a Source #

Cut an array to form a new (smaller) shape. Errors if the new shape is larger. The old array is reranked to the rank of the new shape first.

>>> cut [2] (array [4] [0..3] :: Array Vector Int)
UnsafeArray [2] [0,1]

cutSuffix :: forall (v :: Type -> Type) a. Vector v a => [Int] -> Array v a -> Array v a Source #

Cut an array to form a new (smaller) shape, using suffix elements. Errors if the new shape is larger. The old array is reranked to the rank of the new shape first.

>>> cutSuffix [2,2] a
UnsafeArray [2,2] [18,19,22,23]

pad :: forall (v :: Type -> Type) a. Vector v a => a -> [Int] -> Array v a -> Array v a Source #

Pad an array to form a new shape, supplying a default value for elements outside the shape of the old array. The old array is reranked to the rank of the new shape first.

>>> pad 0 [5] (array [4] [0..3] :: Array Vector Int)
UnsafeArray [5] [0,1,2,3,0]

lpad :: forall (v :: Type -> Type) a. Vector v a => a -> [Int] -> Array v a -> Array v a Source #

Left pad an array to form a new shape, supplying a default value for elements outside the shape of the old array.

>>> lpad 0 [5] (array [4] [0..3] :: Array Vector Int)
UnsafeArray [5] [0,0,1,2,3]
>>> pretty $ lpad 0 [3,3] (range [2,2] :: Array Vector Int)
[[0,0,0],
 [0,0,1],
 [0,2,3]]

reshape :: forall (v :: Type -> Type) a. Vector v a => [Int] -> Array v a -> Array v a Source #

Reshape an array (with the same or less number of elements).

>>> pretty $ reshape [4,3,2] a
[[[0,1],
  [2,3],
  [4,5]],
 [[6,7],
  [8,9],
  [10,11]],
 [[12,13],
  [14,15],
  [16,17]],
 [[18,19],
  [20,21],
  [22,23]]]

flat :: forall {k} (v :: k -> Type) (a :: k). Array v a -> Array v a Source #

Make an Array Vector single dimensional.

>>> pretty $ flat (range [2,2])
[0,1,2,3]
>>> pretty (flat $ toScalar 0)
[0]

repeat :: forall (v :: Type -> Type) a. Vector v a => [Int] -> Array v a -> Array v a Source #

Reshape an array, repeating the original array. The shape of the array should be a suffix of the new shape.

>>> pretty $ repeat [2,2,2] (array [2] [1,2])
[[[1,2],
  [1,2]],
 [[1,2],
  [1,2]]]
repeat ds (toScalar x) == konst ds x

cycle :: forall (v :: Type -> Type) a. Vector v a => [Int] -> Array v a -> Array v a Source #

Reshape an array, cycling through the elements without regard to the original shape.

>>> pretty $ cycle [2,2,2] (array [3] [1,2,3])
[[[1,2],
  [3,1]],
 [[2,3],
  [1,2]]]

rerank :: forall {k} (v :: k -> Type) (a :: k). Int -> Array v a -> Array v a Source #

Change rank by adding new dimensions at the front, if the new rank is greater, or combining dimensions (from left to right) into rows, if the new rank is lower.

>>> shape (rerank 4 a)
[1,2,3,4]
>>> shape (rerank 2 a)
[6,4]
flat == rerank 1

reorder :: forall (v :: Type -> Type) a. Vector v a => Dims -> Array v a -> Array v a Source #

Change the order of dimensions.

>>> pretty $ reorder [2,0,1] a
[[[0,4,8],
  [12,16,20]],
 [[1,5,9],
  [13,17,21]],
 [[2,6,10],
  [14,18,22]],
 [[3,7,11],
  [15,19,23]]]

squeeze :: forall {k} (v :: k -> Type) (a :: k). Array v a -> Array v a Source #

Remove single dimensions.

>>> let sq = array [2,1,3,4,1] [1..24] :: Array Vector Int
>>> shape $ squeeze sq
[2,3,4]
>>> shape $ squeeze (singleton 0)
[]

elongate :: forall {k} (v :: k -> Type) (a :: k). Dim -> Array v a -> Array v a Source #

Insert a single dimension at the supplied position.

>>> shape $ elongate 1 a
[2,1,3,4]
>>> elongate 0 (toScalar 1)
UnsafeArray [1] [1]

transpose :: forall (v :: Type -> Type) a. Vector v a => Array v a -> Array v a Source #

Reverse indices eg transposes the element Aijk to Akji.

>>> index (transpose a) [1,0,0] == index a [0,0,1]
True
>>> pretty $ transpose (array [2,2,2] [1..8])
[[[1,5],
  [3,7]],
 [[2,6],
  [4,8]]]

inflate :: forall (v :: Type -> Type) a. Vector v a => Dim -> Int -> Array v a -> Array v a Source #

Inflate an array by inserting a new dimension given a supplied dimension and size.

alt name: replicate

>>> pretty $ inflate 0 2 (array [3] [0,1,2])
[[0,1,2],
 [0,1,2]]

intercalate :: forall (v :: Type -> Type) a. (Vector v a, Vector v (Array v a)) => Dim -> Array v a -> Array v a -> Array v a Source #

Intercalate an array along dimensions.

>>> pretty $ intercalate 2 (konst [2,3] 0) a
[[[0,0,1,0,2,0,3],
  [4,0,5,0,6,0,7],
  [8,0,9,0,10,0,11]],
 [[12,0,13,0,14,0,15],
  [16,0,17,0,18,0,19],
  [20,0,21,0,22,0,23]]]

intersperse :: forall (v :: Type -> Type) a. (Vector v a, Vector v (Array v a)) => Dim -> a -> Array v a -> Array v a Source #

Intersperse an element along dimensions.

>>> pretty $ intersperse 2 0 a
[[[0,0,1,0,2,0,3],
  [4,0,5,0,6,0,7],
  [8,0,9,0,10,0,11]],
 [[12,0,13,0,14,0,15],
  [16,0,17,0,18,0,19],
  [20,0,21,0,22,0,23]]]

concats :: forall (v :: Type -> Type) a. Vector v a => Dims -> Int -> Array v a -> Array v a Source #

Concatenate and replace dimensions, creating a new dimension at the supplied postion.

>>> pretty $ concats [0,1] 1 a
[[0,4,8,12,16,20],
 [1,5,9,13,17,21],
 [2,6,10,14,18,22],
 [3,7,11,15,19,23]]

reverses :: forall (v :: Type -> Type) a. Vector v a => Dims -> Array v a -> Array v a Source #

Reverses element order along specified dimensions.

>>> pretty $ reverses [0,1] a
[[[20,21,22,23],
  [16,17,18,19],
  [12,13,14,15]],
 [[8,9,10,11],
  [4,5,6,7],
  [0,1,2,3]]]

rotates :: forall (v :: Type -> Type) a. Vector v a => Dims -> [Int] -> Array v a -> Array v a Source #

Rotate an array by/along dimensions & offsets.

>>> pretty $ rotates [1] [2] a
[[[8,9,10,11],
  [0,1,2,3],
  [4,5,6,7]],
 [[20,21,22,23],
  [12,13,14,15],
  [16,17,18,19]]]

Sorting

sorts :: forall (v :: Type -> Type) a. (Ord (v a), Vector v a, Vector v Int, Vector v (Array v a)) => Dims -> Array v a -> Array v a Source #

Sort an array along the supplied dimensions.

>>> sorts [0] (array [2,2] [2,3,1,4])
UnsafeArray [2,2] [1,4,2,3]
>>> sorts [1] (array [2,2] [2,3,1,4])
UnsafeArray [2,2] [2,3,1,4]
>>> sorts [0,1] (array [2,2] [2,3,1,4])
UnsafeArray [2,2] [1,2,3,4]

sortsBy :: forall (v :: Type -> Type) b a. (Ord (v b), Vector v a, Vector v Int, Vector v (Array v a)) => Dims -> (Array v a -> Array v b) -> Array v a -> Array v a Source #

The indices into the array if it were sorted by a comparison function along the dimensions supplied.

>>> import Data.Ord (Down (..))
>>> sortsBy [0] (fmapA Down) (array [2,2] [2,3,1,4])
UnsafeArray [2,2] [2,3,1,4]

orders :: forall (v :: Type -> Type) a. (Ord (v a), Vector v Int, Vector v a, Vector v (Array v a)) => Dims -> Array v a -> Array v Int Source #

The indices into the array if it were sorted along the dimensions supplied.

>>> orders [0] (array [2,2] [2,3,1,4])
UnsafeArray [2] [1,0]

ordersBy :: forall (v :: Type -> Type) b a. (Ord (v b), Vector v Int, Vector v a, Vector v (Array v a)) => Dims -> (Array v a -> Array v b) -> Array v a -> Array v Int Source #

The indices into the array if it were sorted by a comparison function along the dimensions supplied.

>>> import Data.Ord (Down (..))
>>> ordersBy [0] (fmapA Down) (array [2,2] [2,3,1,4])
UnsafeArray [2] [0,1]

Transmission

transmit :: forall (v :: Type -> Type) b c a. (Vector v b, Vector v c, Vector v (Array v b), Vector v (Array v c)) => (Array v a -> Array v b -> Array v c) -> Array v a -> Array v b -> Array v c Source #

Apply a binary array function to two arrays where the shape of the first array is a prefix of the second array. No checks on shape.

>>> a = array [2,3] [0..5]
>>> pretty $ transmit (zipWith (+)) (toScalar 1) a
[[1,2,3],
 [4,5,6]]

transmitSafe :: forall (v :: Type -> Type) b c a. (Vector v b, Vector v c, Vector v (Array v b), Vector v (Array v c)) => (Array v a -> Array v b -> Array v c) -> Array v a -> Array v b -> Maybe (Array v c) Source #

Apply a binary array function to two arrays where the shape of the first array is a prefix of the second array. Checks shape.

>>> a = array [2,3] [0..5]
>>> transmitSafe (zipWith (+)) (array [3] [1,2,3]) a
Nothing

transmitOp :: forall (v :: Type -> Type) a b c. (Vector v a, Vector v b, Vector v c, Vector v (Array v a), Vector v (Array v b), Vector v (Array v c)) => (a -> b -> c) -> Array v a -> Array v b -> Array v c Source #

Transmit an operation if the first array is a prefix of the second or vice versa.

>>> pretty $ transmitOp (*) a (asArray [1,2])
[[[0,1,2,3],
  [4,5,6,7],
  [8,9,10,11]],
 [[24,26,28,30],
  [32,34,36,38],
  [40,42,44,46]]]

telecasts :: forall (v :: Type -> Type) a b c. (Vector v a, Vector v b, Vector v c, Vector v (Array v a), Vector v (Array v b), Vector v (Array v c)) => Dims -> Dims -> (Array v a -> Array v b -> Array v c) -> Array v a -> Array v b -> Array v c Source #

Apply a binary array function to two arrays with matching shapes across the supplied dimensions. No check on shapes.

>>> a = array [2,3] [0..5]
>>> b = array [3] [0..2]
>>> pretty $ telecasts [1] [0] (concatenate 0) a b
[[0,1,2],
 [3,4,5],
 [0,1,2]]

telecastsSafe :: forall (v :: Type -> Type) a b c. (Vector v a, Vector v b, Vector v c, Vector v (Array v a), Vector v (Array v b), Vector v (Array v c)) => Dims -> Dims -> (Array v a -> Array v b -> Array v c) -> Array v a -> Array v b -> Maybe (Array v c) Source #

Apply a binary array function to two arrays with matching shapes across the supplied dimensions. Checks shape.

>>> a = array [2,3] [0..5]
>>> b = array [1] [1]
>>> telecastsSafe [0] [0] (zipWith (+)) a b
Nothing

Row specializations

pattern (:<) :: Vector v a => Array v a -> Array v a -> Array v a infix 5 Source #

Convenience pattern for row extraction and consolidation at the beginning of an Array.

>>> (x:<xs) = array [4] [0..3]
>>> x
UnsafeArray [] [0]
>>> xs
UnsafeArray [3] [1,2,3]
>>> (x:<xs)
UnsafeArray [4] [0,1,2,3]

cons :: forall (v :: Type -> Type) a. Vector v a => Array v a -> Array v a -> Array v a Source #

Add a new row

>>> pretty $ cons (array [2] [0,1]) (array [2,2] [2,3,4,5])
[[0,1],
 [2,3],
 [4,5]]

uncons :: forall (v :: Type -> Type) a. Vector v a => Array v a -> (Array v a, Array v a) Source #

split an array into the first row and the remaining rows.

>>> uncons (array [3,2] [0..5])
(UnsafeArray [2] [0,1],UnsafeArray [2,2] [2,3,4,5])

pattern (:>) :: Vector v a => Array v a -> Array v a -> Array v a infix 5 Source #

Convenience pattern for row extraction and consolidation at the end of an Array.

>>> (xs:>x) = array [4] [0..3]
>>> x
UnsafeArray [] [3]
>>> xs
UnsafeArray [3] [0,1,2]
>>> (xs:>x)
UnsafeArray [4] [0,1,2,3]

snoc :: forall (v :: Type -> Type) a. Vector v a => Array v a -> Array v a -> Array v a Source #

Add a new row at the end

>>> pretty $ snoc (array [2,2] [0,1,2,3]) (array [2] [4,5])
[[0,1],
 [2,3],
 [4,5]]

unsnoc :: forall (v :: Type -> Type) a. Vector v a => Array v a -> (Array v a, Array v a) Source #

split an array into the initial rows and the last row.

>>> unsnoc (array [3,2] [0..5])
(UnsafeArray [2,2] [0,1,2,3],UnsafeArray [2] [4,5])

Shape specializations

iota :: forall (v :: Type -> Type). Vector v Int => Int -> Array v Int Source #

Vector specialisation of range

>>> iota 5
UnsafeArray [5] [0,1,2,3,4]

Math

uniform :: forall g m a (v :: Type -> Type). (StatefulGen g m, UniformRange a, Vector v a) => g -> [Int] -> (a, a) -> m (Array v a) Source #

Generate an array of uniform random variates between a range.

>>> import System.Random.Stateful hiding (uniform)
>>> g <- newIOGenM (mkStdGen 42)
>>> u <- uniform g [2,3,4] (0,9 :: Int)
>>> pretty u
[[[0,7,0,2],
  [1,7,4,2],
  [5,9,8,2]],
 [[9,8,1,0],
  [2,2,8,2],
  [2,8,0,6]]]