Safe Haskell | None |
---|---|
Language | Haskell2010 |
Arrays with a fixed shape, with a HMatrix representation.
Synopsis
- newtype Array s a = Array {}
- index :: forall s a. (HasShape s, Element a, Container Vector a) => Array s a -> [Int] -> a
- tabulate :: forall s a. (HasShape s, Element a) => ([Int] -> a) -> Array s a
- shape :: forall a s. HasShape s => Array s a -> [Int]
- toDynamic :: (HasShape s, Element a) => Array s a -> Array a
- toFixed :: (HasShape s, Element a) => Array s a -> Array s a
- fromFixed :: (HasShape s, Element a) => Array s a -> Array s a
- reshape :: forall a s s'. (Size s ~ Size s', HasShape s, HasShape s', Container Vector a) => Array s a -> Array s' a
- transpose :: forall a s. (Element a, Container Vector a, HasShape s, HasShape (Reverse s)) => Array s a -> Array (Reverse s) a
- diag :: forall a s. (HasShape s, HasShape '[Minimum s], Element a, Container Vector a) => Array s a -> Array '[Minimum s] a
- ident :: forall a s. (Element a, Container Vector a, HasShape s, Additive a, Multiplicative a) => Array s a
- singleton :: (Element a, Container Vector a, HasShape s) => a -> Array s a
- selects :: forall ds s s' a. (HasShape s, HasShape ds, HasShape s', s' ~ DropIndexes s ds, Element a, Container Vector a) => Proxy ds -> [Int] -> Array s a -> Array s' a
- selectsExcept :: forall ds s s' a. (HasShape s, HasShape ds, HasShape s', s' ~ TakeIndexes s ds, Element a, Container Vector a) => Proxy ds -> [Int] -> Array s a -> Array s' a
- folds :: forall ds st si so a b. (HasShape st, HasShape ds, HasShape si, HasShape so, si ~ DropIndexes st ds, so ~ TakeIndexes st ds, Element a, Container Vector a, Element b, Container Vector b) => (Array si a -> b) -> Proxy ds -> Array st a -> Array so b
- concatenate :: forall a s0 s1 d s. (CheckConcatenate d s0 s1 s, Concatenate d s0 s1 ~ s, HasShape s0, HasShape s1, HasShape s, KnownNat d, Element a, Container Vector a) => Proxy d -> Array s0 a -> Array s1 a -> Array s a
- insert :: forall a s s' d i. (DropIndex s d ~ s', CheckInsert d i s, KnownNat i, KnownNat d, HasShape s, HasShape s', HasShape (Insert d s), Element a, Container Vector a) => Proxy d -> Proxy i -> Array s a -> Array s' a -> Array (Insert d s) a
- append :: forall a d s s'. (DropIndex s d ~ s', CheckInsert d (Dimension s d - 1) s, KnownNat (Dimension s d - 1), KnownNat d, HasShape s, HasShape s', HasShape (Insert d s), Element a, Container Vector a) => Proxy d -> Array s a -> Array s' a -> Array (Insert d s) a
- reorder :: forall a ds s. (HasShape ds, HasShape s, HasShape (Reorder s ds), CheckReorder ds s, Element a, Container Vector a) => Proxy ds -> Array s a -> Array (Reorder s ds) a
- expand :: forall s s' a b c. (HasShape s, HasShape s', HasShape ((++) s s'), Element a, Container Vector a, Element b, Container Vector b, Element c) => (a -> b -> c) -> Array s a -> Array s' b -> Array ((++) s s') c
- slice :: forall (pss :: [[Nat]]) s s' a. (HasShape s, HasShape s', KnownNatss pss, KnownNat (Rank pss), s' ~ Ranks pss, Element a, Container Vector a) => Proxy pss -> Array s a -> Array s' a
- squeeze :: forall s t a. t ~ Squeeze s => Array s a -> Array t a
- type Scalar a = Array ('[] :: [Nat]) a
- fromScalar :: (Element a, Container Vector a, HasShape ('[] :: [Nat])) => Array ('[] :: [Nat]) a -> a
- toScalar :: (Element a, Container Vector a, HasShape ('[] :: [Nat])) => a -> Array ('[] :: [Nat]) a
- type Vector s a = Array '[s] a
- type Matrix m n a = Array '[m, n] a
- col :: forall m n a. (Element a, Container Vector a, KnownNat m, KnownNat n, HasShape '[m, n]) => Int -> Matrix m n a -> Vector n a
- row :: forall m n a. (Element a, Container Vector a, KnownNat m, KnownNat n, HasShape '[m, n]) => Int -> Matrix m n a -> Vector n a
- safeCol :: forall m n a j. (Element a, Container Vector a, True ~ CheckIndex j n, KnownNat j, KnownNat m, KnownNat n, HasShape '[m, n]) => Proxy j -> Matrix m n a -> Vector n a
- safeRow :: forall m n a j. (Element a, Container Vector a, True ~ CheckIndex j m, KnownNat j, KnownNat m, KnownNat n, HasShape '[m, n]) => Proxy j -> Matrix m n a -> Vector n a
- mmult :: forall m n k a. (KnownNat k, KnownNat m, KnownNat n, HasShape [m, n], Ring a, Numeric a) => Array [m, k] a -> Array [k, n] a -> Array [m, n] a
Documentation
>>>
:set -XDataKinds
>>>
:set -XOverloadedLists
>>>
:set -XTypeFamilies
>>>
:set -XFlexibleContexts
>>>
let s = [1] :: Array ('[] :: [Nat]) Int -- scalar
>>>
let v = [1,2,3] :: Array '[3] Int -- vector
>>>
let m = [0..11] :: Array '[3,4] Int -- matrix
>>>
let a = [1..24] :: Array '[2,3,4] Int
a multidimensional array with a type-level shape
>>>
let a = [1..24] :: Array '[2,3,4] Int
>>>
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]]]
>>>
[1,2,3] :: Array '[2,2] Int
[[*** Exception: NumHaskException {errorMessage = "shape mismatch"}
Instances
Representation
index :: forall s a. (HasShape s, Element a, Container Vector a) => Array s a -> [Int] -> a Source #
with no fmap, we supply the representable API
tabulate :: forall s a. (HasShape s, Element a) => ([Int] -> a) -> Array s a Source #
tabulate an array with a generating function
>>>
tabulate [2,3,4] ((1+) . flatten [2,3,4]) == a
True
Conversion
shape :: forall a s. HasShape s => Array s a -> [Int] Source #
Get shape of an Array as a value.
>>>
shape a
[2,3,4]
Operators
reshape :: forall a s s'. (Size s ~ Size s', HasShape s, HasShape s', Container Vector a) => Array s a -> Array s' a Source #
Reshape an array (with the same number of elements).
>>>
reshape a :: Array '[4,3,2] 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]]]
transpose :: forall a s. (Element a, Container Vector a, HasShape s, HasShape (Reverse s)) => Array s a -> Array (Reverse s) a Source #
Reverse indices eg transposes the element Aijk to Akji.
>>>
index (transpose a) [1,0,0] == index a [0,0,1]
True
diag :: forall a s. (HasShape s, HasShape '[Minimum s], Element a, Container Vector a) => Array s a -> Array '[Minimum s] a Source #
Extract the diagonal of an array.
>>>
diag (ident :: Array '[3,2] Int)
[1, 1]
ident :: forall a s. (Element a, Container Vector a, HasShape s, Additive a, Multiplicative a) => Array s a Source #
The identity array.
>>>
ident :: Array '[3,2] Int
[[1, 0], [0, 1], [0, 0]]
singleton :: (Element a, Container Vector a, HasShape s) => a -> Array s a Source #
Create an array composed of a single value.
>>>
singleton one :: Array '[3,2] Int
[[1, 1], [1, 1], [1, 1]]
selects :: forall ds s s' a. (HasShape s, HasShape ds, HasShape s', s' ~ DropIndexes s ds, Element a, Container Vector a) => Proxy ds -> [Int] -> Array s a -> Array s' a Source #
Select an array along dimensions.
>>>
let s = selects (Proxy :: Proxy '[0,1]) [1,1] a
>>>
:t s
s :: Array '[4] Int
>>>
s
[17, 18, 19, 20]
selectsExcept :: forall ds s s' a. (HasShape s, HasShape ds, HasShape s', s' ~ TakeIndexes s ds, Element a, Container Vector a) => Proxy ds -> [Int] -> Array s a -> Array s' a Source #
Select an index except along specified dimensions.
>>>
let s = selectsExcept (Proxy :: Proxy '[2]) [1,1] a
>>>
:t s
s :: Array '[4] Int
>>>
s
[17, 18, 19, 20]
folds :: forall ds st si so a b. (HasShape st, HasShape ds, HasShape si, HasShape so, si ~ DropIndexes st ds, so ~ TakeIndexes st ds, Element a, Container Vector a, Element b, Container Vector b) => (Array si a -> b) -> Proxy ds -> Array st a -> Array so b Source #
Fold along specified dimensions.
>>>
folds sum (Proxy :: Proxy '[1]) a
[68, 100, 132]
concatenate :: forall a s0 s1 d s. (CheckConcatenate d s0 s1 s, Concatenate d s0 s1 ~ s, HasShape s0, HasShape s1, HasShape s, KnownNat d, Element a, Container Vector a) => Proxy d -> Array s0 a -> Array s1 a -> Array s a Source #
Concatenate along a dimension.
>>>
:t concatenate (Proxy :: Proxy 1) a a
concatenate (Proxy :: Proxy 1) a a :: Array '[2, 6, 4] Int
insert :: forall a s s' d i. (DropIndex s d ~ s', CheckInsert d i s, KnownNat i, KnownNat d, HasShape s, HasShape s', HasShape (Insert d s), Element a, Container Vector a) => Proxy d -> Proxy i -> Array s a -> Array s' a -> Array (Insert d s) a Source #
Insert along a dimension at a position.
>>>
insert (Proxy :: Proxy 2) (Proxy :: Proxy 0) a ([100..105])
[[[100, 1, 2, 3, 4], [101, 5, 6, 7, 8], [102, 9, 10, 11, 12]], [[103, 13, 14, 15, 16], [104, 17, 18, 19, 20], [105, 21, 22, 23, 24]]]
append :: forall a d s s'. (DropIndex s d ~ s', CheckInsert d (Dimension s d - 1) s, KnownNat (Dimension s d - 1), KnownNat d, HasShape s, HasShape s', HasShape (Insert d s), Element a, Container Vector a) => Proxy d -> Array s a -> Array s' a -> Array (Insert d s) a Source #
Insert along a dimension at the end.
>>>
:t append (Proxy :: Proxy 0) a
append (Proxy :: Proxy 0) a :: Array '[3, 4] Int -> Array '[3, 3, 4] Int
reorder :: forall a ds s. (HasShape ds, HasShape s, HasShape (Reorder s ds), CheckReorder ds s, Element a, Container Vector a) => Proxy ds -> Array s a -> Array (Reorder s ds) a Source #
Change the order of dimensions.
>>>
let r = reorder (Proxy :: Proxy '[2,0,1]) a
>>>
:t r
r :: Array '[4, 2, 3] Int
expand :: forall s s' a b c. (HasShape s, HasShape s', HasShape ((++) s s'), Element a, Container Vector a, Element b, Container Vector b, Element c) => (a -> b -> c) -> Array s a -> Array s' b -> Array ((++) s s') 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.
https://en.wikipedia.org/wiki/Tensor_product
The concept of a tensor product is a dense crossroad, and a complete treatment is elsewhere. To quote:
... 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.
>>>
expand (*) v v
[[1, 2, 3], [2, 4, 6], [3, 6, 9]]
slice :: forall (pss :: [[Nat]]) s s' a. (HasShape s, HasShape s', KnownNatss pss, KnownNat (Rank pss), s' ~ Ranks pss, Element a, Container Vector a) => Proxy pss -> Array s a -> Array s' a Source #
Select elements along positions in every dimension.
>>>
let s = slice (Proxy :: Proxy '[[0,1],[0,2],[1,2]]) a
>>>
:t s
s :: Array '[2, 2, 2] Int
>>>
s
[[[2, 3], [10, 11]], [[14, 15], [22, 23]]]
>>>
let s = squeeze $ slice (Proxy :: Proxy '[ '[0], '[0], '[0]]) a
>>>
:t s
s :: Array '[] Int
>>>
s
1
squeeze :: forall s t a. t ~ Squeeze s => Array s a -> Array t a Source #
Remove single dimensions.
>>>
let a = [1..24] :: Array '[2,1,3,4,1] Int
>>>
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]]]]]>>>
squeeze 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]]]
>>>
squeeze ([1] :: Array '[1,1] Double)
1.0
Scalar
type Scalar a = Array ('[] :: [Nat]) a Source #
An Array '[] a despite being a Scalar is never-the-less a one-element vector under the hood. Unification of representation is unexplored.
fromScalar :: (Element a, Container Vector a, HasShape ('[] :: [Nat])) => Array ('[] :: [Nat]) a -> a Source #
Unwrapping scalars is probably a performance bottleneck.
>>>
let s = [3] :: Array ('[] :: [Nat]) Int
>>>
fromScalar s
3
toScalar :: (Element a, Container Vector a, HasShape ('[] :: [Nat])) => a -> Array ('[] :: [Nat]) a Source #
Convert a number to a scalar.
>>>
:t toScalar 2
toScalar 2 :: Num a => Array '[] a
Vector
Matrix
col :: forall m n a. (Element a, Container Vector a, KnownNat m, KnownNat n, HasShape '[m, n]) => Int -> Matrix m n a -> Vector n a Source #
Extract specialised to a matrix.
>>>
col 1 m
[1, 5, 9]
row :: forall m n a. (Element a, Container Vector a, KnownNat m, KnownNat n, HasShape '[m, n]) => Int -> Matrix m n a -> Vector n a Source #
Extract specialised to a matrix.
>>>
row 1 m
[4, 5, 6, 7]
safeCol :: forall m n a j. (Element a, Container Vector a, True ~ CheckIndex j n, KnownNat j, KnownNat m, KnownNat n, HasShape '[m, n]) => Proxy j -> Matrix m n a -> Vector n a Source #
Column extraction checked at type level.
>>>
safeCol (Proxy :: Proxy 1) m
[1, 5, 9]
>>>
safeCol (Proxy :: Proxy 4) m
... ... index outside range ...
safeRow :: forall m n a j. (Element a, Container Vector a, True ~ CheckIndex j m, KnownNat j, KnownNat m, KnownNat n, HasShape '[m, n]) => Proxy j -> Matrix m n a -> Vector n a Source #
Row extraction checked at type level.
>>>
safeRow (Proxy :: Proxy 1) m
[4, 5, 6, 7]
>>>
safeRow (Proxy :: Proxy 3) m
... ... index outside range ...
mmult :: forall m n k a. (KnownNat k, KnownNat m, KnownNat n, HasShape [m, n], Ring a, Numeric a) => Array [m, k] a -> Array [k, n] a -> Array [m, n] a Source #
Matrix multiplication.
This is dot sum (*) specialised to matrices
>>>
let a = [1, 2, 3, 4] :: Array '[2, 2] Int
>>>
let b = [5, 6, 7, 8] :: Array '[2, 2] Int
>>>
a
[[1, 2], [3, 4]]
>>>
b
[[5, 6], [7, 8]]
>>>
mmult a b
[[19, 22], [43, 50]]