Îõ³h$O®LZ©      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨None'(,-./>?ÀÁÂÉÔÖ×Ùìî i numhask-arrayReflect a list of list of Nats numhask-arrayReflect a list of Nats$ numhask-array™The Shape type holds a [Nat] at type level and the equivalent [Int] at value level. Using [Int] as the index for an array nicely represents the practical interests and constraints downstream of this high-level API: densely-packed numbers (reals or integrals), indexed and layered.' numhask-arrayNumber of dimensions( numhask-array&The shape of a list of element indexes) numhask-arrayNumber of elements* numhask-array.convert from n-dim shape index to a flat indexflatten [2,3,4] [1,1,1]17flatten [] [1,1,1]0+ numhask-array*convert from a flat index to a shape indexshapen [2,3,4] 17[1,1,1], numhask-arraycheckIndex i n checks if i& is a valid index of a list of length n- numhask-arraycheckIndexes is n check if is' are valid indexes of a list of length n. numhask-array,dimension i is the i'th dimension of a Shape/ numhask-arrayminimum value in a list0 numhask-array$drop the i'th dimension from a shapedropIndex [2, 3, 4] 1[2,4]1 numhask-arrayaddIndex s i d adds a new dimension to shape s at position iaddIndex [2,4] 1 3[2,3,4]2 numhask-array´convert a list of position that references a final shape to one that references positions relative to an accumulator. Deletions are from the left and additions are from the right. deletionsposRelative [0,1][0,0] additions%reverse (posRelative (reverse [1,0]))[0,0]3 numhask-arrayèdrop dimensions of a shape according to a list of positions (where position refers to the initial shape)dropIndexes [2, 3, 4] [1, 0][4]4 numhask-arrayinsert a list of dimensions according to position and dimension lists. Note that the list of positions references the final shape and not the initial shape.addIndexes [4] [1,0] [3,2][2,3,4]5 numhask-array4take list of dimensions according to position lists.takeIndexes [2,3,4] [2,0][4,2]6 numhask-arrayÔturn a list of included positions for a given rank into a list of excluded positionsexclude 3 [1,2][0]7 numhask-array concatenateconcatenate' 1 [2,3,4] [2,3,4][2,6,4]8 numhask-array incAt d s increments the index at d of shape s by one.9 numhask-array decAt d s decrements the index at d of shape s by one.: numhask-array reorder' s i" reorders the dimensions of shape s" according to a list of positions ireorder' [2,3,4] [2,0,1][4,2,3]; numhask-arrayremove 1's from a list<  !"#$%&'()*+,-./0123456789:;<$%&"# '!( ).*+/,-1024356 7  :;89None,./8>?ÀÁÂÉÔ×Ùî'`!C numhask-array1a multidimensional array with a value-level shape1let a = fromFlatList [2,3,4] [1..24] :: Array Inta[[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], [[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]]G numhask-arrayconvert from a list!fromFlatList [2,3,4] [1..24] == aTrueH numhask-arrayconvert to a flat list.toFlatList a == [1..24]TrueI numhask-arrayextract an element at index iindex a [1,2,3]24J numhask-array,tabulate an array with a generating function.tabulate [2,3,4] ((1+) . flatten [2,3,4]) == aTrueK numhask-array4Reshape an array (with the same number of elements).reshape [4,3,2] 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]]]L numhask-array+Reverse indices eg transposes the element Aijk to Akji..index (transpose a) [1,0,0] == index a [0,0,1]TrueM numhask-arrayThe identity array. ident [3,2][[1, 0], [0, 1], [0, 0]]N numhask-array!Extract the diagonal of an array.diag (ident [3,2])[1, 1]O numhask-array+Create an array composed of a single value.singleton [3,2] one[[1, 1], [1, 1], [1, 1]]P numhask-array!Select an array along dimensions.let s = selects [0,1] [1,1] as[17, 18, 19, 20]Q numhask-arraySelect an index except along specified dimensions!let s = selectsExcept [2] [1,1] as[17, 18, 19, 20]R numhask-array Fold along specified dimensions.folds sum [1] a[68, 100, 132]S numhask-array&Extracts dimensions to an outer layer.let e = extracts [1,2] ashape <$> extracts [0] a[[3,4], [3,4]]T numhask-array Extracts except dimensions to an outer layer.let e = extractsExcept [1,2] ashape <$> extracts [0] a[[3,4], [3,4]]U numhask-array&Join inner and outer dimension layers.let e = extracts [1,0] alet j = joins [1,0] ea == jTrueV numhask-array+Maps a function along specified dimensions.shape $ maps (transpose) [1] a[4,3,2]W numhask-arrayConcatenate along a dimension.shape $ concatenate 1 a a[2,6,4]X numhask-array'Insert along a dimension at a position.,insert 2 0 a (fromFlatList [2,3] [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]]]Y numhask-array$Insert along a dimension at the end.*append 2 a (fromFlatList [2,3] [100..105])[[[1, 2, 3, 4, 100], [5, 6, 7, 8, 101], [9, 10, 11, 12, 102]], [[13, 14, 15, 16, 103], [17, 18, 19, 20, 104], [21, 22, 23, 24, 105]]]Z numhask-arraychange the order of dimensionslet r = reorder [2,0,1] ar [[[1, 5, 9], [13, 17, 21]], [[2, 6, 10], [14, 18, 22]], [[3, 7, 11], [15, 19, 23]], [[4, 8, 12], [16, 20, 24]]][ numhask-array6Product 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]]\ numhask-array4Apply an array of functions to each array of values. v) v [[1, 2, 3], [2, 4, 6], [3, 6, 9]].let b = fromFlatList [2,3] [1..6] :: Array Int5contract sum [1,2] (apply (fmap (*) b) (transpose b)) [[14, 32], [32, 77]]] numhask-arrayå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, and allowing a binary operator other than multiplication..let b = fromFlatList [2,3] [1..6] :: Array Int/contract sum [1,2] (expand (*) b (transpose b)) [[14, 32], [32, 77]]^ numhask-array‹A generalisation of a dot operation, which is a multiplicative expansion of two arrays and sum contraction along the middle two dimensions.matrix multiplication.let b = fromFlatList [2,3] [1..6] :: Array Intdot sum (*) b (transpose b) [[14, 32], [32, 77]] inner product,let v = fromFlatList [3] [1..3] :: Array Intdot sum (*) v v14ñmatrix-vector multiplication Note that an `Array Int` with shape [3] is neither a row vector nor column vector. ^Î is not turning the vector into a matrix and then using matrix multiplication.dot sum (*) v b [9, 12, 15]dot sum (*) b v[14, 32]_ numhask-arrayArray multiplication.matrix multiplication.let b = fromFlatList [2,3] [1..6] :: Array Intmult b (transpose b) [[14, 32], [32, 77]] inner product,let v = fromFlatList [3] [1..3] :: Array Intmult v v14matrix-vector multiplicationmult v b [9, 12, 15]mult b v[14, 32]` numhask-array3Select elements along positions in every dimension.#let s = slice [[0,1],[0,2],[1,2]] as [[[2, 3], [10, 11]], [[14, 15], [22, 23]]]a numhask-arrayRemove single dimensions.6let a' = fromFlatList [2,1,3,4,1] [1..24] :: Array Intshape $ squeeze a'[2,3,4]b numhask-array8Unwrapping scalars is probably a performance bottleneck.(let s = fromFlatList [] [3] :: Array Int fromScalar s3c numhask-arrayConvert a number to a scalar. :t toScalar 2&toScalar 2 :: FromInteger a => Array ad numhask-array Extract specialised to a matrix.row 1 m [4, 5, 6, 7]e numhask-arrayextract specialised to a matrixcol 1 m [1, 5, 9]f numhask-arraymatrix multiplication+This is dot sum (*) specialised to matrices4let a = fromFlatList [2,2] [1, 2, 3, 4] :: Array Int4let b = fromFlatList [2,2] [5, 6, 7, 8] :: Array Inta[[1, 2], [3, 4]]b[[5, 6], [7, 8]] mmult a b [[19, 22], [43, 50]]$CDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdef$CDEFGHIJKLNMOPQRSTUVWXYZ[\]^_`abcedfNone,./5678>?ÀÁÂÉÎÔÖ×ÙìîKH%n numhask-array 2https://en.wikipedia.org/wiki/Matrix_(mathematics) Wiki Matrixo numhask-array >https://en.wikipedia.org/wiki/Vector_(mathematics_and_physics) Wiki Vectorp numhask-array 3https://en.wikipedia.org/wiki/Scalarr_(mathematics) Wiki Scalar‰An Array '[] a despite being a Scalar is never-the-less a one-element vector under the hood. Unification of representation is unexplored.q numhask-array0a multidimensional array with a type-level shape:set -XDataKinds[1..24] :: Array '[2,3,4] Int[[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], [[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]]][1,2,3] :: Array '[2,2] IntÁ*** Exception: NumHaskException {errorMessage = "shape mismatch"}t numhask-array!Get shape of an Array as a value.shape a[2,3,4]u numhask-array9convert to a dynamic array with shape at the value level.v numhask-array'Use a dynamic array in a fixed context.+import qualified NumHask.Array.Dynamic as Dõwith (D.fromFlatList [2,3,4] [1..24]) (selects (Proxy :: Proxy '[0,1]) [1,1] :: Array '[2,3,4] Int -> Array '[4] Int)[17, 18, 19, 20]w numhask-array4Reshape 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]]]x numhask-array+Reverse indices eg transposes the element Aijk to Akji..index (transpose a) [1,0,0] == index a [0,0,1]Truey numhask-arrayThe identity array.ident :: Array '[3,2] Int[[1, 0], [0, 1], [0, 0]]z numhask-array!Extract the diagonal of an array. diag (ident :: Array '[3,2] Int)[1, 1]{ numhask-array+Create an array composed of a single value.!singleton one :: Array '[3,2] Int[[1, 1], [1, 1], [1, 1]]| numhask-array!Select an array along dimensions./let s = selects (Proxy :: Proxy '[0,1]) [1,1] a:t ss :: Array '[4] Ints[17, 18, 19, 20]} numhask-arraySelect an index except along specified dimensions.3let s = selectsExcept (Proxy :: Proxy '[2]) [1,1] a:t ss :: Array '[4] Ints[17, 18, 19, 20]~ numhask-array Fold along specified dimensions.!folds sum (Proxy :: Proxy '[1]) a[68, 100, 132] numhask-array&Extracts dimensions to an outer layer.*let e = extracts (Proxy :: Proxy '[1,2]) a:t e#e :: Array '[3, 4] (Array '[2] Int)€ numhask-array Extracts except dimensions to an outer layer.0let e = extractsExcept (Proxy :: Proxy '[1,2]) a:t e#e :: Array '[2] (Array '[3, 4] Int) numhask-array&Join inner and outer dimension layers.*let e = extracts (Proxy :: Proxy '[1,0]) a:t e#e :: Array '[3, 2] (Array '[4] Int)'let j = joins (Proxy :: Proxy '[1,0]) e:t jj :: Array '[2, 3, 4] Inta == jTrue‚ numhask-array+Maps a function along specified dimensions.+:t maps (transpose) (Proxy :: Proxy '[1]) aÀmaps (transpose) (Proxy :: Proxy '[1]) a :: Array '[4, 3, 2] Intƒ numhask-arrayConcatenate along a dimension.%:t concatenate (Proxy :: Proxy 1) a a:concatenate (Proxy :: Proxy 1) a a :: Array '[2, 6, 4] Int„ numhask-array'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]]]… numhask-array$Insert along a dimension at the end.:t append (Proxy :: Proxy 0) aappend (Proxy :: Proxy 0) a. :: Array '[3, 4] Int -> Array '[3, 3, 4] Int† numhask-arrayChange the order of dimensions.+let r = reorder (Proxy :: Proxy '[2,0,1]) a:t rr :: Array '[4, 2, 3] Int‡ numhask-array6Product 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]]ˆ numhask-array4Apply an array of functions to each array of values. v) v [[1, 2, 3], [2, 4, 6], [3, 6, 9]]èArrays can't be applicative functors in haskell because the changes in shape are reflected in the types. :t applyþapply :: (HasShape s, HasShape s', HasShape (s ++ s')) => Array s (a -> b) -> Array s' a -> Array (s ++ s') b > :t ( *) ( *.) :: Applicative f => f (a -> b) -> f a -> f b"let b = [1..6] :: Array '[2,3] IntÇcontract sum (Proxy :: Proxy '[1,2]) (apply (fmap (*) b) (transpose b)) [[14, 32], [32, 77]]‰ numhask-arrayå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, and allowing a binary operator other than multiplication."let b = [1..6] :: Array '[2,3] IntÁcontract sum (Proxy :: Proxy '[1,2]) (expand (*) b (transpose b)) [[14, 32], [32, 77]]Š numhask-array‹A generalisation of a dot operation, which is a multiplicative expansion of two arrays and sum contraction along the middle two dimensions.matrix multiplication"let b = [1..6] :: Array '[2,3] Intdot sum (*) b (transpose b) [[14, 32], [32, 77]] inner product let v = [1..3] :: Array '[3] Int:t dot sum (*) v v dot sum (*) v v :: Array '[] Intdot sum (*) v v14êmatrix-vector multiplication (Note how the vector doesn't need to be converted to a row or column vector)dot sum (*) v b [9, 12, 15]dot sum (*) b v[14, 32],dot allows operation on mis-shaped matrices:$let m23 = [1..6] :: Array '[2,3] Int#let m12 = [1,2] :: Array '[1,2] Intshape $ dot sum (*) m23 m12[2,2]Ëthe algorithm ignores excess positions within the contracting dimension(s):m23 shape: 2 3m12 shape: 1 2res shape: 2 25FIXME: work out whether this is a feature or a bug...&find instances of a vector in a matrix=let cs = fromList ("abacbaab" :: [Char]) :: Array '[4,2] Char2let v = fromList ("ab" :: [Char]) :: Vector 2 Chardot (all id) (==) cs v[True, False, False, True]‹ numhask-arrayArray multiplication.matrix multiplication"let b = [1..6] :: Array '[2,3] Intmult b (transpose b) [[14, 32], [32, 77]] inner product let v = [1..3] :: Array '[3] Int :t mult v vmult v v :: Array '[] Intmult v v14matrix-vector multiplicationmult v b [9, 12, 15]mult b v[14, 32]Œ numhask-array3Select elements along positions in every dimension.5let s = slice (Proxy :: Proxy '[[0,1],[0,2],[1,2]]) a:t ss :: Array '[2, 2, 2] Ints [[[2, 3], [10, 11]], [[14, 15], [22, 23]]]?let s = squeeze $ slice (Proxy :: Proxy '[ '[0], '[0], '[0]]) a:t ss :: Array '[] Ints1 numhask-arrayRemove single dimensions.)let a = [1..24] :: Array '[2,1,3,4,1] Inta[[[[[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Ž numhask-array8Unwrapping scalars is probably a performance bottleneck.'let s = [3] :: Array ('[] :: [Nat]) Int fromScalar s3 numhask-arrayConvert a number to a scalar. :t toScalar 2*toScalar 2 :: FromInteger a => Array '[] a numhask-array Extract specialised to a matrix.row 1 m [4, 5, 6, 7]‘ numhask-array%Row extraction checked at type level.safeRow (Proxy :: Proxy 1) m [4, 5, 6, 7]safeRow (Proxy :: Proxy 3) m...... index outside range...’ numhask-array Extract specialised to a matrix.col 1 m [1, 5, 9]“ numhask-array(Column extraction checked at type level.safeCol (Proxy :: Proxy 1) m [1, 5, 9]safeCol (Proxy :: Proxy 4) m...... index outside range...” numhask-arrayMatrix 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] Inta[[1, 2], [3, 4]]b[[5, 6], [7, 8]] mmult a b [[19, 22], [43, 50]]'nopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”'qrsvtuwxzy{|}~€‚ƒ„…†‡ˆ‰Š‹ŒpŽon’“‘”NoneKÝã  !"#$%&'()*+,-./0123456789:;nopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”©      !"#$%&'())*+,-./0123456789:;<=>?@ABCDEFGGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrsGGIHtuNOPQRSTUVWXYZ[\]^_`abcdefgvhwixyz{|}~€‚ƒj„nomlpk…+numhask-array-0.10.0-LHF9CY3U1IZAU5vv0zQgLyNumHask.Array.ShapeNumHask.Array.DynamicNumHask.Array.Fixed NumHask.Array KnownNatssnatValss KnownNatsnatValsFilterSqueeze CheckReorderReorderInsert CheckInsertCheckConcatenate ConcatenateExclude!! TakeIndexes AddIndexesGo AddIndexes DropIndexes PosRelativeGo PosRelative ReverseGoReverseAddIndex DropIndex++DropTakeMinimum Dimension CheckIndexes CheckIndexSizeRanksRankHasShapetoShapeShapeshapeValrankrankssizeflattenshapen checkIndex checkIndexes dimensionminimum dropIndexaddIndex posRelative dropIndexes addIndexes takeIndexesexclude concatenate'incAtdecAtreorder'squeeze' $fHasShape: $fHasShape[] $fKnownNats: $fKnownNats[] $fKnownNatss:$fKnownNatss[] $fShowShapeArrayshapeunArray fromFlatList toFlatListindextabulatereshape transposeidentdiag singletonselects selectsExceptfoldsextractsextractsExceptjoinsmaps concatenateinsertappendreorderexpandapplycontractdotmultslicesqueeze fromScalartoScalarrowcolmmult $fShowArray$fTraversableArray$fFoldableArray$fFunctorArray $fEqArray $fOrdArray$fGenericArrayMatrixVectorScalar toDynamicwithsafeRowsafeCol $fIsListArray$fEpsilonArray$fMeetSemiLatticeArray$fJoinSemiLatticeArray$fDivisiveActionArraya$fSubtractiveActionArraya$fAdditiveActionArraya$fMultiplicativeActionArraya$fSubtractiveArray$fAdditiveArray$fRepresentableArray$fDistributiveArray$fMultiplicativeArray