Copyright  (c) Alexey Kuleshevich 2018 

License  BSD3 
Maintainer  Alexey Kuleshevich <lehins@yandex.ru> 
Stability  experimental 
Portability  nonportable 
Safe Haskell  None 
Language  Haskell2010 
Massiv is a library, that allows creation and manipulation of arrays in parallel and
sequentially. Depending on the representation (r
), an
will have
certain properties that are unique to that particular representation, but all of them will share
the same trait, that an array is simply a mapping from an index (Array
r ix eix
) of an arbitrary
dimension to an element (e
) of some value. Which means that some of the array types are
pretty classic and are represented by a contiguous chunk of memory reserved for the elements,
namely arrays with Manifest
representations:
B
 The most basic type of array that can hold any type of element in a boxed form, i.e. each element is a pointer to the actual value, therefore it is also the slowest representation. Elements are kept in a Weak Head Normal Form (WHNF).N
 Similar toB
, is also a boxed type, except it's elements are always kept in a Normal Form (NF). This property is very useful for parallel processing, i.e. when callingcompute
you do want all of your elements to be fully evaluated.S
 Is a type of array that is backed by pinned memory, therefore pointers to those arrays can be passed to FFI calls, because Garbage Collector (GC) is guaranteed not to move it. Elements must be an instance ofStorable
class. It is just as efficient asP
andU
arrays, except it is subject to fragmentation.U
 Unboxed representation. Elements must be an instance ofUnbox
class.P
 Array that can hold Haskell primitives, such asInt
,Word
,Double
, etc. Any element must be an instance ofPrim
class.M
 General manifest array type, that any of the above representations can be converted to in constant time usingtoManifest
.
While at the same time, there are arrays that only describe how values for it's elements can be computed, and have no memory overhead on their own.
D
 delayed array that is a mere function from an index to an element. Crucial representation for fusing computation. UsecomputeAs
in order to load array intoManifest
representation.DI
 delayed interleaved array. Same asD
, but performced better with unbalanced computation, when evaluation one element takes much longer than it's neighbor.DW
 delayed windowed array. This peculiar representation allows for very fastStencil
computation.
Other Array types:
L
andLN
 those types aren't particularly useful on their own, but because of their unique ability to be converted to and from nested lists in constant time, provide an amazing intermediary for list/array conversion.
Most of the Manifest
arrays are capable of inplace mutation. Check out
Data.Massiv.Array.Mutable module for available functionality.
Many of the function names exported by this package will clash with the ones from Prelude, hence it can be more convenient to import like this:
import Prelude as P import Data.Massiv.Array as A
 makeArray :: Construct r ix e => Comp > ix > (ix > e) > Array r ix e
 makeArrayR :: Construct r ix e => r > Comp > ix > (ix > e) > Array r ix e
 makeVectorR :: Construct r Ix1 e => r > Comp > Ix1 > (Ix1 > e) > Array r Ix1 e
 singleton :: Construct r ix e => Comp > e > Array r ix e
 range :: Comp > Int > Int > Array D Ix1 Int
 rangeStep :: Comp > Int > Int > Int > Array D Ix1 Int
 enumFromN :: Num e => Comp > e > Int > Array D Ix1 e
 enumFromStepN :: Num e => Comp > e > e > Int > Array D Ix1 e
 getComp :: Construct r ix e => Array r ix e > Comp
 setComp :: Construct r ix e => Comp > Array r ix e > Array r ix e
 compute :: (Load r' ix e, Mutable r ix e) => Array r' ix e > Array r ix e
 computeAs :: (Load r' ix e, Mutable r ix e) => r > Array r' ix e > Array r ix e
 computeProxy :: (Load r' ix e, Mutable r ix e) => proxy r > Array r' ix e > Array r ix e
 computeSource :: forall r' r ix e. (Source r' ix e, Mutable r ix e) => Array r' ix e > Array r ix e
 clone :: Mutable r ix e => Array r ix e > Array r ix e
 convert :: (Manifest r' ix e, Mutable r ix e) => Array r' ix e > Array r ix e
 convertAs :: (Mutable r' ix e, Mutable r ix e, Typeable ix, Typeable e) => r > Array r' ix e > Array r ix e
 convertProxy :: (Mutable r' ix e, Mutable r ix e, Typeable ix, Typeable e) => proxy r > Array r' ix e > Array r ix e
 fromRaggedArray :: (Ragged r' ix e, Mutable r ix e) => Array r' ix e > Either ShapeError (Array r ix e)
 fromRaggedArray' :: (Ragged r' ix e, Mutable r ix e) => Array r' ix e > Array r ix e
 size :: Size r ix e => Array r ix e > ix
 elemsCount :: Size r ix e => Array r ix e > Int
 isEmpty :: Size r ix e => Array r ix e > Bool
 (!?) :: Manifest r ix e => Array r ix e > ix > Maybe e
 (!) :: Manifest r ix e => Array r ix e > ix > e
 (??) :: Manifest r ix e => Maybe (Array r ix e) > ix > Maybe e
 index :: Manifest r ix e => Array r ix e > ix > Maybe e
 index' :: Manifest r ix e => Array r ix e > ix > e
 defaultIndex :: Manifest r ix e => e > Array r ix e > ix > e
 borderIndex :: Manifest r ix e => Border e > Array r ix e > ix > e
 evaluateAt :: Source r ix e => Array r ix e > ix > e
 map :: Source r ix e' => (e' > e) > Array r ix e' > Array D ix e
 imap :: Source r ix e' => (ix > e' > e) > Array r ix e' > Array D ix e
 mapM_ :: (Source r ix a, Monad m) => (a > m b) > Array r ix a > m ()
 forM_ :: (Source r ix a, Monad m) => Array r ix a > (a > m b) > m ()
 imapM_ :: (Source r ix a, Monad m) => (ix > a > m b) > Array r ix a > m ()
 iforM_ :: (Source r ix a, Monad m) => Array r ix a > (ix > a > m b) > m ()
 mapP_ :: Source r ix a => (a > IO b) > Array r ix a > IO ()
 imapP_ :: Source r ix a => (ix > a > IO b) > Array r ix a > IO ()
 zip :: (Source r1 ix e1, Source r2 ix e2) => Array r1 ix e1 > Array r2 ix e2 > Array D ix (e1, e2)
 zip3 :: (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3) => Array r1 ix e1 > Array r2 ix e2 > Array r3 ix e3 > Array D ix (e1, e2, e3)
 unzip :: Source r ix (e1, e2) => Array r ix (e1, e2) > (Array D ix e1, Array D ix e2)
 unzip3 :: Source r ix (e1, e2, e3) => Array r ix (e1, e2, e3) > (Array D ix e1, Array D ix e2, Array D ix e3)
 zipWith :: (Source r1 ix e1, Source r2 ix e2) => (e1 > e2 > e) > Array r1 ix e1 > Array r2 ix e2 > Array D ix e
 zipWith3 :: (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3) => (e1 > e2 > e3 > e) > Array r1 ix e1 > Array r2 ix e2 > Array r3 ix e3 > Array D ix e
 izipWith :: (Source r1 ix e1, Source r2 ix e2) => (ix > e1 > e2 > e) > Array r1 ix e1 > Array r2 ix e2 > Array D ix e
 izipWith3 :: (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3) => (ix > e1 > e2 > e3 > e) > Array r1 ix e1 > Array r2 ix e2 > Array r3 ix e3 > Array D ix e
 fold :: Source r ix e => (e > e > e) > e > Array r ix e > e
 minimum :: (Source r ix e, Ord e) => Array r ix e > e
 maximum :: (Source r ix e, Ord e) => Array r ix e > e
 sum :: (Source r ix e, Num e) => Array r ix e > e
 product :: (Source r ix e, Num e) => Array r ix e > e
 and :: Source r ix Bool => Array r ix Bool > Bool
 or :: Source r ix Bool => Array r ix Bool > Bool
 all :: Source r ix e => (e > Bool) > Array r ix e > Bool
 any :: Source r ix e => (e > Bool) > Array r ix e > Bool
 foldlS :: Source r ix e => (a > e > a) > a > Array r ix e > a
 foldrS :: Source r ix e => (e > a > a) > a > Array r ix e > a
 ifoldlS :: Source r ix e => (a > ix > e > a) > a > Array r ix e > a
 ifoldrS :: Source r ix e => (ix > e > a > a) > a > Array r ix e > a
 foldlM :: (Source r ix e, Monad m) => (a > e > m a) > a > Array r ix e > m a
 foldrM :: (Source r ix e, Monad m) => (e > a > m a) > a > Array r ix e > m a
 foldlM_ :: (Source r ix e, Monad m) => (a > e > m a) > a > Array r ix e > m ()
 foldrM_ :: (Source r ix e, Monad m) => (e > a > m a) > a > Array r ix e > m ()
 ifoldlM :: (Source r ix e, Monad m) => (a > ix > e > m a) > a > Array r ix e > m a
 ifoldrM :: (Source r ix e, Monad m) => (ix > e > a > m a) > a > Array r ix e > m a
 ifoldlM_ :: (Source r ix e, Monad m) => (a > ix > e > m a) > a > Array r ix e > m ()
 ifoldrM_ :: (Source r ix e, Monad m) => (ix > e > a > m a) > a > Array r ix e > m ()
 foldrFB :: Source r ix e => (e > b > b) > b > Array r ix e > b
 lazyFoldlS :: Source r ix e => (a > e > a) > a > Array r ix e > a
 lazyFoldrS :: Source r ix e => (e > a > a) > a > Array r ix e > a
 foldlP :: Source r ix e => (a > e > a) > a > (b > a > b) > b > Array r ix e > IO b
 foldrP :: Source r ix e => (e > a > a) > a > (a > b > b) > b > Array r ix e > IO b
 ifoldlP :: Source r ix e => (a > ix > e > a) > a > (b > a > b) > b > Array r ix e > IO b
 ifoldrP :: Source r ix e => (ix > e > a > a) > a > (a > b > b) > b > Array r ix e > IO b
 foldlOnP :: Source r ix e => [Int] > (a > e > a) > a > (b > a > b) > b > Array r ix e > IO b
 ifoldlIO :: Source r ix e => [Int] > (a > ix > e > IO a) > a > (b > a > IO b) > b > Array r ix e > IO b
 foldrOnP :: Source r ix e => [Int] > (e > a > a) > a > (a > b > b) > b > Array r ix e > IO b
 ifoldlOnP :: Source r ix e => [Int] > (a > ix > e > a) > a > (b > a > b) > b > Array r ix e > IO b
 ifoldrOnP :: Source r ix e => [Int] > (ix > e > a > a) > a > (a > b > b) > b > Array r ix e > IO b
 ifoldrIO :: Source r ix e => [Int] > (ix > e > a > IO a) > a > (a > b > IO b) > b > Array r ix e > IO b
 transpose :: Source r Ix2 e => Array r Ix2 e > Array D Ix2 e
 transposeInner :: (Index (Lower ix), Source r' ix e) => Array r' ix e > Array D ix e
 transposeOuter :: (Index (Lower ix), Source r' ix e) => Array r' ix e > Array D ix e
 backpermute :: (Source r' ix' e, Index ix) => ix > (ix > ix') > Array r' ix' e > Array D ix e
 resize :: (Index ix', Size r ix e) => ix' > Array r ix e > Maybe (Array r ix' e)
 resize' :: (Index ix', Size r ix e) => ix' > Array r ix e > Array r ix' e
 extract :: Size r ix e => ix > ix > Array r ix e > Maybe (Array (EltRepr r ix) ix e)
 extract' :: Size r ix e => ix > ix > Array r ix e > Array (EltRepr r ix) ix e
 extractFromTo :: Size r ix e => ix > ix > Array r ix e > Maybe (Array (EltRepr r ix) ix e)
 append :: (Source r1 ix e, Source r2 ix e) => Dim > Array r1 ix e > Array r2 ix e > Maybe (Array D ix e)
 append' :: (Source r1 ix e, Source r2 ix e) => Dim > Array r1 ix e > Array r2 ix e > Array D ix e
 splitAt :: (Size r ix e, r' ~ EltRepr r ix) => Dim > Int > Array r ix e > Maybe (Array r' ix e, Array r' ix e)
 splitAt' :: (Size r ix e, r' ~ EltRepr r ix) => Dim > Int > Array r ix e > (Array r' ix e, Array r' ix e)
 traverse :: (Source r1 ix1 e1, Index ix) => ix > ((ix1 > e1) > ix > e) > Array r1 ix1 e1 > Array D ix e
 traverse2 :: (Source r1 ix1 e1, Source r2 ix2 e2, Index ix) => ix > ((ix1 > e1) > (ix2 > e2) > ix > e) > Array r1 ix1 e1 > Array r2 ix2 e2 > Array D ix e
 (!>) :: OuterSlice r ix e => Array r ix e > Int > Elt r ix e
 (!?>) :: OuterSlice r ix e => Array r ix e > Int > Maybe (Elt r ix e)
 (??>) :: OuterSlice r ix e => Maybe (Array r ix e) > Int > Maybe (Elt r ix e)
 (<!) :: InnerSlice r ix e => Array r ix e > Int > Elt r ix e
 (<!?) :: InnerSlice r ix e => Array r ix e > Int > Maybe (Elt r ix e)
 (<??) :: InnerSlice r ix e => Maybe (Array r ix e) > Int > Maybe (Elt r ix e)
 (<!>) :: Slice r ix e => Array r ix e > (Dim, Int) > Elt r ix e
 (<!?>) :: Slice r ix e => Array r ix e > (Dim, Int) > Maybe (Elt r ix e)
 (<??>) :: Slice r ix e => Maybe (Array r ix e) > (Dim, Int) > Maybe (Elt r ix e)
 fromList :: (Nested LN Ix1 e, Nested L Ix1 e, Ragged L Ix1 e, Mutable r Ix1 e) => Comp > [e] > Array r Ix1 e
 fromLists :: (Nested LN ix e, Nested L ix e, Ragged L ix e, Mutable r ix e) => Comp > [ListItem ix e] > Maybe (Array r ix e)
 fromLists' :: (Nested LN ix e, Nested L ix e, Ragged L ix e, Mutable r ix e) => Comp > [ListItem ix e] > Array r ix e
 toList :: Source r ix e => Array r ix e > [e]
 toLists :: (Nested LN ix e, Nested L ix e, Construct L ix e, Source r ix e) => Array r ix e > [ListItem ix e]
 toLists2 :: (Source r ix e, Index (Lower ix)) => Array r ix e > [[e]]
 toLists3 :: (Index (Lower (Lower ix)), Index (Lower ix), Source r ix e) => Array r ix e > [[[e]]]
 toLists4 :: (Index (Lower (Lower (Lower ix))), Index (Lower (Lower ix)), Index (Lower ix), Source r ix e) => Array r ix e > [[[[e]]]]
 module Data.Massiv.Array.Mutable
 module Data.Massiv.Core
 module Data.Massiv.Array.Delayed
 module Data.Massiv.Array.Manifest
 module Data.Massiv.Array.Stencil
 module Data.Massiv.Array.Numeric
Construct
:: Construct r ix e  
=> Comp  
> ix  Size of the result array. Negative values will result in an empty array. 
> (ix > e)  Function to generate elements at a particular index 
> Array r ix e 
Create an Array. Resulting type either has to be unambiguously inferred or restricted manually, like in the example below.
>>>
makeArray Seq (3 :. 4) (\ (i :. j) > if i == j then i else 0) :: Array D Ix2 Int
(Array D Seq (3 :. 4) [ [ 0,0,0,0 ] , [ 0,1,0,0 ] , [ 0,0,2,0 ] ])
makeArrayR :: Construct r ix e => r > Comp > ix > (ix > e) > Array r ix e Source #
Just like makeArray
but with ability to specify the result representation as an
argument. Note the U
nboxed type constructor in the below example.
>>>
makeArrayR U Par (2 :> 3 :. 4) (\ (i :> j :. k) > i * i + j * j == k * k)
(Array U Par (2 :> 3 :. 4) [ [ [ True,False,False,False ] , [ False,True,False,False ] , [ False,False,True,False ] ] , [ [ False,True,False,False ] , [ False,False,False,False ] , [ False,False,False,False ] ] ])
makeVectorR :: Construct r Ix1 e => r > Comp > Ix1 > (Ix1 > e) > Array r Ix1 e Source #
Same as makeArrayR
, but restricted to 1dimensional arrays.
Create an Array with a single element.
range :: Comp > Int > Int > Array D Ix1 Int Source #
Create a vector with a range of Int
s incremented by 1.
range k0 k1 == rangeStep k0 k1 1
>>>
range Seq 1 6
(Array D Seq (5) [ 1,2,3,4,5 ])>>>
range Seq (2) 3
(Array D Seq (5) [ 2,1,0,1,2 ])
Same as range
, but with a custom step.
>>>
rangeStep Seq 1 2 6
(Array D Seq (3) [ 1,3,5 ])
Same as enumFromStepN
with step delta = 1
.
>>>
enumFromN Seq (5 :: Double) 3
(Array D Seq (3) [ 5.0,6.0,7.0 ])
:: Num e  
=> Comp  
> e 

> e 

> Int 

> Array D Ix1 e 
Create a vector with length n
that has it's 0th value set to x
and gradually increasing
with step
delta until the end. Similar to:
. Major difference is that fromList'
Seq
$ take
n [x,
x + delta ..]fromList
constructs an Array
with manifest
representation, while enumFromStepN
is delayed.
>>>
enumFromStepN Seq 1 (0.1 :: Double) 5
(Array D Seq (5) [ 1.0,1.1,1.2,1.3,1.4 ])
Compute
setComp :: Construct r ix e => Comp > Array r ix e > Array r ix e Source #
Set computation strategy for this array
computeAs :: (Load r' ix e, Mutable r ix e) => r > Array r' ix e > Array r ix e Source #
Just as compute
, but let's you supply resulting representation type as an argument.
Examples
>>>
computeAs P $ range Seq 0 10
(Array P Seq (10) [ 0,1,2,3,4,5,6,7,8,9 ])
computeProxy :: (Load r' ix e, Mutable r ix e) => proxy r > Array r' ix e > Array r ix e Source #
Same as convert
and convertAs
, but let's you supply resulting representation type as a proxy
argument.
Examples
Useful for cases when representation constructor isn't available for some reason:
>>>
computeProxy (Nothing :: Maybe P) $ range Seq 0 10
(Array P Seq (10) [ 0,1,2,3,4,5,6,7,8,9 ])
Since: 0.1.1
computeSource :: forall r' r ix e. (Source r' ix e, Mutable r ix e) => Array r' ix e > Array r ix e Source #
clone :: Mutable r ix e => Array r ix e > Array r ix e Source #
O(n)  Make an exact immutable copy of an Array.
convert :: (Manifest r' ix e, Mutable r ix e) => Array r' ix e > Array r ix e Source #
O(n)  conversion between manifest types, except when source and result arrays are of the same representation, in which case it is an O(1) operation.
convertAs :: (Mutable r' ix e, Mutable r ix e, Typeable ix, Typeable e) => r > Array r' ix e > Array r ix e Source #
Same as convert
, but let's you supply resulting representation type as an argument.
convertProxy :: (Mutable r' ix e, Mutable r ix e, Typeable ix, Typeable e) => proxy r > Array r' ix e > Array r ix e Source #
fromRaggedArray :: (Ragged r' ix e, Mutable r ix e) => Array r' ix e > Either ShapeError (Array r ix e) Source #
Convert a ragged array into a usual rectangular shaped one.
fromRaggedArray' :: (Ragged r' ix e, Mutable r ix e) => Array r' ix e > Array r ix e Source #
Same as fromRaggedArray
, but will throw an error if its shape is not
rectangular.
Size
elemsCount :: Size r ix e => Array r ix e > Int Source #
O(1)  Get the number of elements in the array
Indexing
index' :: Manifest r ix e => Array r ix e > ix > e Source #
O(1)  Lookup an element in the array. Throw an error if index is out of bounds.
defaultIndex :: Manifest r ix e => e > Array r ix e > ix > e Source #
O(1)  Lookup an element in the array, while using default element when index is out of bounds.
borderIndex :: Manifest r ix e => Border e > Array r ix e > ix > e Source #
O(1)  Lookup an element in the array. Use a border resolution technique when index is out of bounds.
evaluateAt :: Source r ix e => Array r ix e > ix > e Source #
This is just like index'
function, but it allows getting values from
delayed arrays as well as manifest. As the name suggests, indexing into a
delayed array at the same index multiple times will cause evaluation of the
value each time and can destroy the performace if used without care.
Mapping
map :: Source r ix e' => (e' > e) > Array r ix e' > Array D ix e Source #
Map a function over an array
imap :: Source r ix e' => (ix > e' > e) > Array r ix e' > Array D ix e Source #
Map an index aware function over an array
Monadic
mapM_ :: (Source r ix a, Monad m) => (a > m b) > Array r ix a > m () Source #
Map a monadic function over an array sequentially, while discarding the result.
Examples
>>>
mapM_ print $ rangeStep 10 12 60
10 22 34 46 58
forM_ :: (Source r ix a, Monad m) => Array r ix a > (a > m b) > m () Source #
Just like mapM_
, except with flipped arguments.
Examples
Here is a common way of iterating N times using a for loop in an imperative language with mutation being an obvious side effect:
>>>
:m + Data.IORef
>>>
var < newIORef 0 :: IO (IORef Int)
>>>
forM_ (range 0 1000) $ \ i > modifyIORef' var (+i)
>>>
readIORef var
499500
imapM_ :: (Source r ix a, Monad m) => (ix > a > m b) > Array r ix a > m () Source #
Map a monadic index aware function over an array sequentially, while discarding the result.
Examples
>>>
imapM_ (curry print) $ range 10 15
(0,10) (1,11) (2,12) (3,13) (4,14)
iforM_ :: (Source r ix a, Monad m) => Array r ix a > (ix > a > m b) > m () Source #
Just like imapM_
, except with flipped arguments.
mapP_ :: Source r ix a => (a > IO b) > Array r ix a > IO () Source #
Map an IO action, over an array in parallel, while discarding the result.
imapP_ :: Source r ix a => (ix > a > IO b) > Array r ix a > IO () Source #
Map an index aware IO action, over an array in parallel, while discarding the result.
Zipping
zip :: (Source r1 ix e1, Source r2 ix e2) => Array r1 ix e1 > Array r2 ix e2 > Array D ix (e1, e2) Source #
Zip two arrays
zip3 :: (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3) => Array r1 ix e1 > Array r2 ix e2 > Array r3 ix e3 > Array D ix (e1, e2, e3) Source #
Zip three arrays
unzip :: Source r ix (e1, e2) => Array r ix (e1, e2) > (Array D ix e1, Array D ix e2) Source #
Unzip two arrays
unzip3 :: Source r ix (e1, e2, e3) => Array r ix (e1, e2, e3) > (Array D ix e1, Array D ix e2, Array D ix e3) Source #
Unzip three arrays
zipWith :: (Source r1 ix e1, Source r2 ix e2) => (e1 > e2 > e) > Array r1 ix e1 > Array r2 ix e2 > Array D ix e Source #
Zip two arrays with a function. Resulting array will be an intersection of source arrays in case their dimensions do not match.
zipWith3 :: (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3) => (e1 > e2 > e3 > e) > Array r1 ix e1 > Array r2 ix e2 > Array r3 ix e3 > Array D ix e Source #
Just like zipWith
, except zip three arrays with a function.
izipWith :: (Source r1 ix e1, Source r2 ix e2) => (ix > e1 > e2 > e) > Array r1 ix e1 > Array r2 ix e2 > Array D ix e Source #
Just like zipWith
, except with an index aware function.
izipWith3 :: (Source r1 ix e1, Source r2 ix e2, Source r3 ix e3) => (ix > e1 > e2 > e3 > e) > Array r1 ix e1 > Array r2 ix e2 > Array r3 ix e3 > Array D ix e Source #
Just like zipWith3
, except with an index aware function.
Folding
All folding is done in a rowmajor order.
Unstructured folds
Functions in this section will fold any Source
array with respect to the inner
Comp
utation strategy setting.
:: Source r ix e  
=> (e > e > e)  Folding function (like with left fold, first argument is an accumulator) 
> e  Initial element. Has to be neutral with respect to the folding function. 
> Array r ix e  Source array 
> e 
O(n)  Unstructured fold of an array.
minimum :: (Source r ix e, Ord e) => Array r ix e > e Source #
O(n)  Compute minimum of all elements.
maximum :: (Source r ix e, Ord e) => Array r ix e > e Source #
O(n)  Compute maximum of all elements.
product :: (Source r ix e, Num e) => Array r ix e > e Source #
O(n)  Compute product of all elements.
and :: Source r ix Bool => Array r ix Bool > Bool Source #
O(n)  Compute conjunction of all elements.
or :: Source r ix Bool => Array r ix Bool > Bool Source #
O(n)  Compute disjunction of all elements.
all :: Source r ix e => (e > Bool) > Array r ix e > Bool Source #
Determines whether all element of the array satisfy the predicate.
any :: Source r ix e => (e > Bool) > Array r ix e > Bool Source #
Determines whether any element of the array satisfies the predicate.
Sequential folds
Functions in this section will fold any Source
array sequentially, regardless of the inner
Comp
utation strategy setting.
foldlS :: Source r ix e => (a > e > a) > a > Array r ix e > a Source #
O(n)  Left fold, computed sequentially.
foldrS :: Source r ix e => (e > a > a) > a > Array r ix e > a Source #
O(n)  Right fold, computed sequentially.
ifoldlS :: Source r ix e => (a > ix > e > a) > a > Array r ix e > a Source #
O(n)  Left fold with an index aware function, computed sequentially.
ifoldrS :: Source r ix e => (ix > e > a > a) > a > Array r ix e > a Source #
O(n)  Right fold with an index aware function, computed sequentially.
Monadic
foldlM :: (Source r ix e, Monad m) => (a > e > m a) > a > Array r ix e > m a Source #
O(n)  Monadic left fold.
foldrM :: (Source r ix e, Monad m) => (e > a > m a) > a > Array r ix e > m a Source #
O(n)  Monadic right fold.
foldlM_ :: (Source r ix e, Monad m) => (a > e > m a) > a > Array r ix e > m () Source #
O(n)  Monadic left fold, that discards the result.
foldrM_ :: (Source r ix e, Monad m) => (e > a > m a) > a > Array r ix e > m () Source #
O(n)  Monadic right fold, that discards the result.
ifoldlM :: (Source r ix e, Monad m) => (a > ix > e > m a) > a > Array r ix e > m a Source #
O(n)  Monadic left fold with an index aware function.
ifoldrM :: (Source r ix e, Monad m) => (ix > e > a > m a) > a > Array r ix e > m a Source #
O(n)  Monadic right fold with an index aware function.
ifoldlM_ :: (Source r ix e, Monad m) => (a > ix > e > m a) > a > Array r ix e > m () Source #
O(n)  Monadic left fold with an index aware function, that discards the result.
ifoldrM_ :: (Source r ix e, Monad m) => (ix > e > a > m a) > a > Array r ix e > m () Source #
O(n)  Monadic right fold with an index aware function, that discards the result.
Special folds
foldrFB :: Source r ix e => (e > b > b) > b > Array r ix e > b Source #
Version of foldr that supports foldr/build
list fusion implemented by GHC.
lazyFoldlS :: Source r ix e => (a > e > a) > a > Array r ix e > a Source #
O(n)  Left fold, computed sequentially with lazy accumulator.
lazyFoldrS :: Source r ix e => (e > a > a) > a > Array r ix e > a Source #
O(n)  Right fold, computed sequentially with lazy accumulator.
Parallel folds
Note It is important to compile with threaded withrtsopts=N
flags, otherwise there will be
no parallelization.
Functions in this section will fold any Source
array in parallel, regardless of the inner
Comp
utation strategy setting. All of the parallel structured folds are performed inside IO
monad, because referential transparency can't generally be preserved and results will depend on the
number of cores/capabilities that computation is being performed on.
In contrast to sequential folds, each parallel folding function accepts two functions and two initial elements as arguments. This is necessary because an array is first split into chunks, which folded individually on separate cores with the first function, and the results of those folds are further folded with the second function.
:: Source r ix e  
=> (a > e > a)  Folding function 
> a  Accumulator. Will be applied to 
> (b > a > b)  Chunk results folding function 
> b  Accumulator for results of chunks folding. 
> Array r ix e  
> IO b 
O(n)  Left fold, computed in parallel. Parallelization of folding is implemented in such a
way that an array is split into a number of chunks of equal length, plus an extra one for the
left over. Number of chunks is the same as number of available cores (capabilities) plus one, and
each chunk is individually folded by a separate core with a function g
. Results from folding
each chunk are further folded with another function f
, thus allowing us to use information
about the structure of an array during folding.
Examples
>>>
foldlP (flip (:)) [] (flip (:)) [] $ makeArrayR U Seq (Ix1 11) id
[[10,9,8,7,6,5,4,3,2,1,0]]
And this is how the result would look like if the above computation would be performed in a
program executed with +RTS N3
, i.e. with 3 capabilities:
>>>
foldlOnP [1,2,3] (flip (:)) [] (flip (:)) [] $ makeArrayR U Seq (Ix1 11) id
[[10,9],[8,7,6],[5,4,3],[2,1,0]]
foldrP :: Source r ix e => (e > a > a) > a > (a > b > b) > b > Array r ix e > IO b Source #
O(n)  Right fold, computed in parallel. Same as foldlP
, except directed
from the last element in the array towards beginning.
Examples
>>>
foldrP (++) [] (:) [] $ makeArray2D (3,4) id
[(0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,2),(1,3),(2,0),(2,1),(2,2),(2,3)]
ifoldlP :: Source r ix e => (a > ix > e > a) > a > (b > a > b) > b > Array r ix e > IO b Source #
O(n)  Left fold with an index aware function, computed in parallel. Just
like foldlP
, except that folding function will receive an index of an
element it is being applied to.
ifoldrP :: Source r ix e => (ix > e > a > a) > a > (a > b > b) > b > Array r ix e > IO b Source #
Just like ifoldrOnP
, but allows you to specify which cores to run computation on.
foldlOnP :: Source r ix e => [Int] > (a > e > a) > a > (b > a > b) > b > Array r ix e > IO b Source #
Just like foldlP
, but allows you to specify which cores (capabilities) to run computation
on. The order in which chunked results will be supplied to function f
is guaranteed to be
consecutive and aligned with the folding direction.
:: Source r ix e  
=> [Int]  List of capabilities 
> (a > ix > e > IO a)  Index aware folding IO action 
> a  Accumulator 
> (b > a > IO b)  Folding action that is applied to results of parallel fold 
> b  Accumulator for chunks folding 
> Array r ix e  
> IO b 
Parallel left fold.
foldrOnP :: Source r ix e => [Int] > (e > a > a) > a > (a > b > b) > b > Array r ix e > IO b Source #
Just like foldrP
, but allows you to specify which cores to run
computation on.
Examples
Number of wokers dictate the result structure:
>>>
foldrOnP [1,2,3] (:) [] (:) [] $ makeArray1D 9 id
[[0,1,2],[3,4,5],[6,7,8]]>>>
foldrOnP [1,2,3] (:) [] (:) [] $ makeArray1D 10 id
[[0,1,2],[3,4,5],[6,7,8],[9]]>>>
foldrOnP [1,2,3] (:) [] (:) [] $ makeArray1D 12 id
[[0,1,2,3],[4,5,6,7],[8,9,10,11]]
But most of the time that structure is of no importance:
>>>
foldrOnP [1,2,3] (++) [] (:) [] $ makeArray1D 10 id
[0,1,2,3,4,5,6,7,8,9]
Same as foldlOnP
, order is guaranteed to be consecutive and in proper direction:
>>>
fmap snd $ foldrOnP [1,2,3] (\x (i, acc) > (i + 1, (i, x):acc)) (1, []) (:) [] $ makeArray1D 11 id
[(4,[0,1,2]),(3,[3,4,5]),(2,[6,7,8]),(1,[9,10])]>>>
fmap (P.zip [4,3..]) <$> foldrOnP [1,2,3] (:) [] (:) [] $ makeArray1D 11 id
[(4,[0,1,2]),(3,[3,4,5]),(2,[6,7,8]),(1,[9,10])]
ifoldlOnP :: Source r ix e => [Int] > (a > ix > e > a) > a > (b > a > b) > b > Array r ix e > IO b Source #
Just like ifoldlP
, but allows you to specify which cores to run
computation on.
ifoldrOnP :: Source r ix e => [Int] > (ix > e > a > a) > a > (a > b > b) > b > Array r ix e > IO b Source #
O(n)  Right fold with an index aware function, computed in parallel.
Same as ifoldlP
, except directed from the last element in the array towards
beginning.
ifoldrIO :: Source r ix e => [Int] > (ix > e > a > IO a) > a > (a > b > IO b) > b > Array r ix e > IO b Source #
Transforming
Transpose
transpose :: Source r Ix2 e => Array r Ix2 e > Array D Ix2 e Source #
Transpose a 2dimensional array
Examples
>>>
let arr = makeArrayR U Seq (2 :. 3) (toLinearIndex (2 :. 3))
>>>
arr
(ArrayU Seq (2 :. 3) [ [ 0,1,2 ] , [ 3,4,5 ] ])>>>
transpose arr
(Array D Seq (3 :. 2) [ [ 0,3 ] , [ 1,4 ] , [ 2,5 ] ])
transposeInner :: (Index (Lower ix), Source r' ix e) => Array r' ix e > Array D ix e Source #
Transpose inner two dimensions of at least rank2 array.
Examples
>>>
let arr = makeArrayR U Seq (2 :> 3 :. 4) fromIx3
>>>
arr
(Array U Seq (2 :> 3 :. 4) [ [ [ (0,0,0),(0,0,1),(0,0,2),(0,0,3) ] , [ (0,1,0),(0,1,1),(0,1,2),(0,1,3) ] , [ (0,2,0),(0,2,1),(0,2,2),(0,2,3) ] ] , [ [ (1,0,0),(1,0,1),(1,0,2),(1,0,3) ] , [ (1,1,0),(1,1,1),(1,1,2),(1,1,3) ] , [ (1,2,0),(1,2,1),(1,2,2),(1,2,3) ] ] ])>>>
transposeInner arr
(Array D Seq (3 :> 2 :. 4) [ [ [ (0,0,0),(0,0,1),(0,0,2),(0,0,3) ] , [ (1,0,0),(1,0,1),(1,0,2),(1,0,3) ] ] , [ [ (0,1,0),(0,1,1),(0,1,2),(0,1,3) ] , [ (1,1,0),(1,1,1),(1,1,2),(1,1,3) ] ] , [ [ (0,2,0),(0,2,1),(0,2,2),(0,2,3) ] , [ (1,2,0),(1,2,1),(1,2,2),(1,2,3) ] ] ])
transposeOuter :: (Index (Lower ix), Source r' ix e) => Array r' ix e > Array D ix e Source #
Transpose outer two dimensions of at least rank2 array.
Examples
>>>
let arr = makeArrayR U Seq (2 :> 3 :. 4) fromIx3
>>>
arr
(Array U Seq (2 :> 3 :. 4) [ [ [ (0,0,0),(0,0,1),(0,0,2),(0,0,3) ] , [ (0,1,0),(0,1,1),(0,1,2),(0,1,3) ] , [ (0,2,0),(0,2,1),(0,2,2),(0,2,3) ] ] , [ [ (1,0,0),(1,0,1),(1,0,2),(1,0,3) ] , [ (1,1,0),(1,1,1),(1,1,2),(1,1,3) ] , [ (1,2,0),(1,2,1),(1,2,2),(1,2,3) ] ] ])>>>
transposeOuter arr
(Array D Seq (2 :> 4 :. 3) [ [ [ (0,0,0),(0,1,0),(0,2,0) ] , [ (0,0,1),(0,1,1),(0,2,1) ] , [ (0,0,2),(0,1,2),(0,2,2) ] , [ (0,0,3),(0,1,3),(0,2,3) ] ] , [ [ (1,0,0),(1,1,0),(1,2,0) ] , [ (1,0,1),(1,1,1),(1,2,1) ] , [ (1,0,2),(1,1,2),(1,2,2) ] , [ (1,0,3),(1,1,3),(1,2,3) ] ] ])
Backpermute
:: (Source r' ix' e, Index ix)  
=> ix  Size of the result array 
> (ix > ix')  A function that maps indices of old array into the source one. 
> Array r' ix' e  Source array. 
> Array D ix e 
Rearrange elements of an array into a new one.
Examples
>>>
let arr = makeArrayR U Seq (2 :> 3 :. 4) fromIx3
>>>
arr
(Array U Seq (2 :> 3 :. 4) [ [ [ (0,0,0),(0,0,1),(0,0,2),(0,0,3) ] , [ (0,1,0),(0,1,1),(0,1,2),(0,1,3) ] , [ (0,2,0),(0,2,1),(0,2,2),(0,2,3) ] ] , [ [ (1,0,0),(1,0,1),(1,0,2),(1,0,3) ] , [ (1,1,0),(1,1,1),(1,1,2),(1,1,3) ] , [ (1,2,0),(1,2,1),(1,2,2),(1,2,3) ] ] ])>>>
backpermute (4 :. 3) (\(i :. j) > 0 :> j :. i) arr
(Array D Seq (4 :. 3) [ [ (0,0,0),(0,1,0),(0,2,0) ] , [ (0,0,1),(0,1,1),(0,2,1) ] , [ (0,0,2),(0,1,2),(0,2,2) ] , [ (0,0,3),(0,1,3),(0,2,3) ] ])
Resize
resize :: (Index ix', Size r ix e) => ix' > Array r ix e > Maybe (Array r ix' e) Source #
O(1)  Changes the shape of an array. Returns Nothing
if total
number of elements does not match the source array.
resize' :: (Index ix', Size r ix e) => ix' > Array r ix e > Array r ix' e Source #
Same as resize
, but will throw an error if supplied dimensions are incorrect.
Extract
:: Size r ix e  
=> ix  Starting index 
> ix  Size fo the resulting array 
> Array r ix e  Source array 
> Maybe (Array (EltRepr r ix) ix e) 
Extract a subarray from within a larger source array. Array that is being extracted must be
fully encapsulated in a source array, otherwise Nothing
is returned,
:: Size r ix e  
=> ix  Starting index 
> ix  Size fo the resulting array 
> Array r ix e  Source array 
> Array (EltRepr r ix) ix e 
Same as extract
, but will throw an error if supplied dimensions are incorrect.
:: Size r ix e  
=> ix  Starting index 
> ix  Index up to which elmenets should be extracted. 
> Array r ix e  Source array. 
> Maybe (Array (EltRepr r ix) ix e) 
Similar to extract
, except it takes starting and ending index. Result array will not include
the ending index.
Append/Split
append :: (Source r1 ix e, Source r2 ix e) => Dim > Array r1 ix e > Array r2 ix e > Maybe (Array D ix e) Source #
Append two arrays together along a particular dimension. Sizes of both arrays must match, with
an allowed exception of the dimension they are being appended along, otherwise Nothing
is
returned.
Examples
Append two 2D arrays along both dimensions. Note that they have the same shape.
>>>
let arrA = makeArrayR U Seq (2 :. 3) (\(i :. j) > ('A', i, j))
>>>
let arrB = makeArrayR U Seq (2 :. 3) (\(i :. j) > ('B', i, j))
>>>
append 1 arrA arrB
Just (Array D Seq (2 :. 6) [ [ ('A',0,0),('A',0,1),('A',0,2),('B',0,0),('B',0,1),('B',0,2) ] , [ ('A',1,0),('A',1,1),('A',1,2),('B',1,0),('B',1,1),('B',1,2) ] ])>>>
append 2 arrA arrB
Just (Array D Seq (4 :. 3) [ [ ('A',0,0),('A',0,1),('A',0,2) ] , [ ('A',1,0),('A',1,1),('A',1,2) ] , [ ('B',0,0),('B',0,1),('B',0,2) ] , [ ('B',1,0),('B',1,1),('B',1,2) ] ])
Now appending arrays with different sizes:
>>>
let arrC = makeArrayR U Seq (2 :. 4) (\(i :. j) > ('C', i, j))
>>>
append 1 arrA arrC
Just (Array D Seq (2 :. 7) [ [ ('A',0,0),('A',0,1),('A',0,2),('C',0,0),('C',0,1),('C',0,2),('C',0,3) ] , [ ('A',1,0),('A',1,1),('A',1,2),('C',1,0),('C',1,1),('C',1,2),('C',1,3) ] ])>>>
append 2 arrA arrC
Nothing
append' :: (Source r1 ix e, Source r2 ix e) => Dim > Array r1 ix e > Array r2 ix e > Array D ix e Source #
:: (Size r ix e, r' ~ EltRepr r ix)  
=> Dim  Dimension along which to split 
> Int  Index along the dimension to split at 
> Array r ix e  Source array 
> Maybe (Array r' ix e, Array r' ix e) 
O(1)  Split an array at an index along a specified dimension.
splitAt' :: (Size r ix e, r' ~ EltRepr r ix) => Dim > Int > Array r ix e > (Array r' ix e, Array r' ix e) Source #
Traverse
:: (Source r1 ix1 e1, Index ix)  
=> ix  Size of the result array 
> ((ix1 > e1) > ix > e)  Function that will receive a source array safe index function and an index for an element it should return a value of. 
> Array r1 ix1 e1  Source array 
> Array D ix e 
Create an array by traversing a source array.
traverse2 :: (Source r1 ix1 e1, Source r2 ix2 e2, Index ix) => ix > ((ix1 > e1) > (ix2 > e2) > ix > e) > Array r1 ix1 e1 > Array r2 ix2 e2 > Array D ix e Source #
Create an array by traversing two source arrays.
Slicing
From the outside
(!>) :: OuterSlice r ix e => Array r ix e > Int > Elt r ix e infixl 4 Source #
O(1)  Slices the array from the outside. For 2dimensional array this will be equivalent of taking a row. Throws an error when index is out of bounds.
Examples
You could say that slicing from outside is synonymous to slicing from the end or slicing at the highermost dimension. For example with rank3 arrays outer slice would be equivalent to getting a page:
>>>
let arr = makeArrayR U Seq (3 :> 2 :. 4) fromIx3
>>>
arr
(Array U Seq (3 :> 2 :. 4) [ [ [ (0,0,0),(0,0,1),(0,0,2),(0,0,3) ] , [ (0,1,0),(0,1,1),(0,1,2),(0,1,3) ] ] , [ [ (1,0,0),(1,0,1),(1,0,2),(1,0,3) ] , [ (1,1,0),(1,1,1),(1,1,2),(1,1,3) ] ] , [ [ (2,0,0),(2,0,1),(2,0,2),(2,0,3) ] , [ (2,1,0),(2,1,1),(2,1,2),(2,1,3) ] ] ])>>>
arr !> 2
(Array M Seq (2 :. 4) [ [ (2,0,0),(2,0,1),(2,0,2),(2,0,3) ] , [ (2,1,0),(2,1,1),(2,1,2),(2,1,3) ] ])
There is nothing wrong with chaining, mixing and matching slicing operators, or even using them to index arrays:
>>>
arr !> 2 !> 0 !> 3
(2,0,3)>>>
arr !> 2 <! 3 ! 0
(2,0,3)>>>
arr !> 2 !> 0 !> 3 == arr ! 2 :> 0 :. 3
True
(??>) :: OuterSlice r ix e => Maybe (Array r ix e) > Int > Maybe (Elt r ix e) infixl 4 Source #
O(1)  Safe slicing continuation from the outside. Similarly to (!>
) slices the array from
the outside, but takes Maybe
array as input and returns Nothing
when index is out of bounds.
Examples
>>>
let arr = makeArrayR U Seq (3 :> 2 :. 4) fromIx3
>>>
arr !?> 2 ??> 0 ??> 3
Just (2,0,3)>>>
arr !?> 2 ??> 0 ??> 1
Nothing>>>
arr !?> 2 ??> 0 ?? 1
Nothing
From the inside
(<!) :: InnerSlice r ix e => Array r ix e > Int > Elt r ix e infixl 4 Source #
O(1)  Similarly to (!>
) slice an array from an opposite direction.
(<!?) :: InnerSlice r ix e => Array r ix e > Int > Maybe (Elt r ix e) infixl 4 Source #
O(1)  Safe slice from the inside
(<??) :: InnerSlice r ix e => Maybe (Array r ix e) > Int > Maybe (Elt r ix e) infixl 4 Source #
O(1)  Safe slicing continuation from the inside
From within
(<!>) :: Slice r ix e => Array r ix e > (Dim, Int) > Elt r ix e infixl 4 Source #
O(1)  Slices the array in any available dimension. Throws an error when index is out of bounds or dimensions is invalid.
arr !> i == arr <!> (rank (size arr), i)
arr <! i == arr <!> (1,i)
(<??>) :: Slice r ix e => Maybe (Array r ix e) > (Dim, Int) > Maybe (Elt r ix e) infixl 4 Source #
O(1)  Safe slicing continuation from within.
Conversion
List
:: (Nested LN Ix1 e, Nested L Ix1 e, Ragged L Ix1 e, Mutable r Ix1 e)  
=> Comp  Computation startegy to use 
> [e]  Nested list 
> Array r Ix1 e 
Convert a flat list into a vector
fromLists :: (Nested LN ix e, Nested L ix e, Ragged L ix e, Mutable r ix e) => Comp > [ListItem ix e] > Maybe (Array r ix e) Source #
O(n)  Convert a nested list into an array. Nested list must be of a rectangular shape, otherwise a runtime error will occur. Also, nestedness must match the rank of resulting array, which should be specified through an explicit type signature.
Note: This function is almost the same (modulo customizable computation strategy) if you
would turn on {}
. For that reason you can also use
fromList
.
Examples
>>>
fromLists Seq [[1,2],[3,4]] :: Maybe (Array U Ix2 Int)
Just (Array U Seq (2 :. 2) [ [ 1,2 ] , [ 3,4 ] ])
>>>
fromLists Par [[[1,2,3]],[[4,5,6]]] :: Maybe (Array U Ix3 Int)
Just (Array U Par (2 :> 1 :. 3) [ [ [ 1,2,3 ] ] , [ [ 4,5,6 ] ] ])
Elements of a boxed array could be lists themselves if necessary, but cannot be ragged:
>>>
fromLists Seq [[[1,2,3]],[[4,5]]] :: Maybe (Array B Ix2 [Int])
Just (Array B Seq (2 :. 1) [ [ [1,2,3] ] , [ [4,5] ] ])>>>
fromLists Seq [[[1,2,3]],[[4,5]]] :: Maybe (Array B Ix3 Int)
Nothing
:: (Nested LN ix e, Nested L ix e, Ragged L ix e, Mutable r ix e)  
=> Comp  Computation startegy to use 
> [ListItem ix e]  Nested list 
> Array r ix e 
Same as fromLists
, but will throw an error on irregular shaped lists.
Examples
Convert a list of lists into a 2D Array
>>>
fromLists' Seq [[1,2],[3,4]] :: Array U Ix2 Int
(Array U Seq (2 :. 2) [ [ 1,2 ] , [ 3,4 ] ])
Above example implemented using GHC's OverloadedLists
extension:
>>>
:set XOverloadedLists
>>>
[[1,2],[3,4]] :: Array U Ix2 Int
(Array U Seq (2 :. 2) [ [ 1,2 ] , [ 3,4 ] ])
Example of failure on ceonversion of an irregular nested list.
>>>
fromLists' Seq [[1],[3,4]] :: Array U Ix2 Int
(Array U *** Exception: Too many elements in a row
toList :: Source r ix e => Array r ix e > [e] Source #
Convert any array to a flat list.
Examples
>>>
toList $ makeArrayR U Seq (2 :. 3) fromIx2
[(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)]
toLists :: (Nested LN ix e, Nested L ix e, Construct L ix e, Source r ix e) => Array r ix e > [ListItem ix e] Source #
O(n)  Convert an array into a nested list. Array rank and list nestedness will always match,
but you can use toList
, toLists2
, etc. if flattening of inner dimensions is desired.
Note: This function is almost the same as toList
.
Examples
>>>
let arr = makeArrayR U Seq (2 :> 1 :. 3) fromIx3
>>>
print arr
(Array U Seq (2 :> 1 :. 3) [ [ [ (0,0,0),(0,0,1),(0,0,2) ] ] , [ [ (1,0,0),(1,0,1),(1,0,2) ] ] ])>>>
toList arr
[[[(0,0,0),(0,0,1),(0,0,2)]],[[(1,0,0),(1,0,1),(1,0,2)]]]
toLists2 :: (Source r ix e, Index (Lower ix)) => Array r ix e > [[e]] Source #
Convert an array with at least 2 dimensions into a list of lists. Inner dimensions will get flattened.
Examples
>>>
toList2 $ makeArrayR U Seq (2 :. 3) fromIx2
[[(0,0),(0,1),(0,2)],[(1,0),(1,1),(1,2)]]>>>
toList2 $ makeArrayR U Seq (2 :> 1 :. 3) fromIx3
[[(0,0,0),(0,0,1),(0,0,2)],[(1,0,0),(1,0,1),(1,0,2)]]
toLists3 :: (Index (Lower (Lower ix)), Index (Lower ix), Source r ix e) => Array r ix e > [[[e]]] Source #
Convert an array with at least 3 dimensions into a 3 deep nested list. Inner dimensions will get flattened.
toLists4 :: (Index (Lower (Lower (Lower ix))), Index (Lower (Lower ix)), Index (Lower ix), Source r ix e) => Array r ix e > [[[[e]]]] Source #
Convert an array with at least 4 dimensions into a 4 deep nested list. Inner dimensions will get flattened.
Mutable
module Data.Massiv.Array.Mutable
Core
module Data.Massiv.Core
Representations
module Data.Massiv.Array.Delayed
module Data.Massiv.Array.Manifest
Stencil
module Data.Massiv.Array.Stencil
module Data.Massiv.Array.Numeric