array-list 0.1.0.0 → 0.2.0.0
raw patch · 5 files changed
+355/−107 lines, 5 filesdep ~doctestPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: doctest
API changes (from Hackage documentation)
+ Data.Array.IsList: arrayNestedList :: ArrayNestedList i e => (i, i) -> NestedList i e -> Array i e
+ Data.Array.IsList: class Ix i => ArrayNestedList i e
+ Data.Array.IsList: instance (GHC.Arr.Ix i, GHC.Arr.Ix j) => Data.Array.IsList.ArrayNestedList (i, j) e
+ Data.Array.IsList: instance (GHC.Arr.Ix i, GHC.Arr.Ix j, GHC.Arr.Ix k) => Data.Array.IsList.ArrayNestedList (i, j, k) e
+ Data.Array.IsList: instance (GHC.Arr.Ix i, GHC.Arr.Ix j, GHC.Arr.Ix k, GHC.Arr.Ix m) => Data.Array.IsList.ArrayNestedList (i, j, k, m) e
+ Data.Array.IsList: instance (GHC.Arr.Ix i, GHC.Arr.Ix j, GHC.Arr.Ix k, GHC.Arr.Ix m, GHC.Arr.Ix n) => Data.Array.IsList.ArrayNestedList (i, j, k, m, n) e
+ Data.Array.IsList: toNestedList :: ArrayNestedList i e => Array i e -> NestedList i e
Files
- CHANGELOG.md +6/−0
- README.md +3/−1
- array-list.cabal +7/−4
- src/Data/Array/IsList.hs +156/−102
- tests/Main.hs +183/−0
CHANGELOG.md view
@@ -1,3 +1,9 @@+## 0.2.0.0++- Added more generic `ArrayNestedList` class with methods `arrayNestedList`+and `toNestedList` to convert between nested lists and+multi-dimensional Arrays with any indices.+ ## 0.1.0.0 - Initial release
README.md view
@@ -1,5 +1,7 @@ # array-list -[IsList](https://hackage.haskell.org/package/base/docs/GHC-Exts.html#t:IsList) instances of [Array](https://hackage.haskell.org/package/array/docs/Data-Array.html#t:Array) for [OverloadedLists](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#overloaded-lists) extension+[IsList](https://hackage.haskell.org/package/base/docs/GHC-Exts.html#t:IsList) instances of [Array](https://hackage.haskell.org/package/array/docs/Data-Array.html#t:Array) for [OverloadedLists](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#overloaded-lists) extension.++Converting between \[nested\] lists and multi-dimensional Arrays. See [docs and usage examples on hackage](http://hackage.haskell.org/package/array-list/docs/Data-Array-IsList.html).
array-list.cabal view
@@ -4,14 +4,17 @@ -- -- see: https://github.com/sol/hpack ----- hash: ed946011242c8c41f9762a9ddaadd8ee8ab793a2361e2cba2c0bcc0d11f18c9d+-- hash: 0dfaca7090560c3bcf961025267c1e7ca59942261400502331a0a3747c130de9 name: array-list-version: 0.1.0.0+version: 0.2.0.0 synopsis: IsList instances of Array for OverloadedLists extension-description: This package provides "orphan" instances 'IsList' for 'Array' data types+description: This package provides "orphan" 'IsList' instances for 'Array' data types with `Integral` indices up to 5 dimensions to allow initializing 'Array's from [nested] lists using 'OverloadedLists' GHC extension.+ .+ It also includes more generic 'arrayNestedList' and 'toNestedList'+ functions to convert between nested lists and 'Array's with any indices. category: Data, Array, List homepage: https://github.com/epoberezkin/array-list#readme bug-reports: https://github.com/epoberezkin/array-list/issues@@ -54,7 +57,7 @@ build-depends: array ==0.5.* , base >=4.7 && <5- , doctest ==0.17.*+ , doctest >=0.16 && <0.18 , doctest-driver-gen ==0.3.* default-language: Haskell2010
src/Data/Array/IsList.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ParallelListComp #-} {-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -16,6 +18,9 @@ -- with `Integral` indices up to 5 dimensions to allow initializing -- 'Array's from [nested] lists using 'OverloadedLists' GHC extension. --+-- It also includes more generic 'arrayNestedList' and 'toNestedList'+-- functions to convert between nested lists and 'Array's with any indices.+-- -- __Examples__: -- -- >>> ["one","two","three"] :: Array Int String@@ -24,15 +29,24 @@ -- >>> [[0,1,2], [10,11,12]] :: Array (Int, Int) Int -- array ((0,0),(1,2)) [((0,0),0),((0,1),1),((0,2),2),((1,0),10),((1,1),11),((1,2),12)] ----- If any of the nested lists contains different number of elements--- for the same dimension, the array creation will fail.+-- If any of the nested lists contains smaller number of elements+-- than the first nested list in the same dimension,+-- the array creation will fail. ----- >>> [[1],[2,3]] :: Array (Int, Int) Int--- array *** Exception: Error in array index+-- >>> [[1,2],[3]] :: Array (Int, Int) Int+-- ... Exception: (Array.!): undefined array element+--+-- Nested lists with larger number of elements will be truncated. module Data.Array.IsList- ( IsList,+ ( -- * IsList+ IsList, fromList, toList,++ -- * ArrayNestedList+ ArrayNestedList,+ arrayNestedList,+ toNestedList, ) where @@ -106,47 +120,20 @@ genericFromList :: (Integral i, Ix i) => [e] -> Array i e genericFromList xs = listArray (0, top xs) xs -splitList :: Integral i => i -> i -> [e] -> [[e]]-splitList _ _ [] = []-splitList l r xs =- let (part, rest) = genericSplitAt (r - l + 1) xs- in part : splitList l r rest- top :: Integral i => [e] -> i top l = genericLength l - 1 -h1 :: [e] -> e-h1 = head--h2 :: [[e]] -> e-h2 = head . head--h3 :: [[[e]]] -> e-h3 = head . h2--h4 :: [[[[e]]]] -> e-h4 = head . h3--inxd :: Integral i => [e] -> [(i, e)]-inxd = zip [0 ..]- instance (Integral i, Integral j, Ix i, Ix j) => IsList (Array (i, j) e) where type Item (Array (i, j) e) = [e] fromList :: [[e]] -> Array (i, j) e- fromList l =- array- ((0, 0), (top l, top $ h1 l))- [ ((i, j), x)- | (i, xs) <- inxd l,- (j, x) <- inxd xs- ]+ fromList l = arrayNestedList bnds l+ where+ bnds = ((0, 0), (top l, top $ head l)) toList :: Array (i, j) e -> [[e]]- toList arr =- let ((_, l), (_, r)) = bounds arr- in splitList l r $ elems arr+ toList = toNestedList instance (Integral i, Integral j, Integral k, Ix i, Ix j, Ix k) =>@@ -154,87 +141,154 @@ where type Item (Array (i, j, k) e) = [[e]] fromList :: [[[e]]] -> Array (i, j, k) e- fromList l =- array- ((0, 0, 0), (top l, top $ h1 l, top $ h2 l))- [ ((i, j, k), x)- | (i, xss) <- inxd l,- (j, xs) <- inxd xss,- (k, x) <- inxd xs- ]+ fromList l = arrayNestedList bnds l+ where+ (h1, h2) = (head l, head h1)+ bnds = ((0, 0, 0), (top l, top h1, top h2)) toList :: Array (i, j, k) e -> [[[e]]]- toList arr =- let ((_, l1, l2), (_, r1, r2)) = bounds arr- in splitList l1 r1- $ splitList l2 r2- $ elems arr+ toList = toNestedList instance- ( Integral i,- Integral j,- Integral k,- Integral m,- Ix i,- Ix j,- Ix k,- Ix m- ) =>+ (Integral i, Integral j, Integral k, Integral m, Ix i, Ix j, Ix k, Ix m) => IsList (Array (i, j, k, m) e) where type Item (Array (i, j, k, m) e) = [[[e]]] fromList :: [[[[e]]]] -> Array (i, j, k, m) e- fromList l =- array- ( (0, 0, 0, 0),- (top l, top $ h1 l, top $ h2 l, top $ h3 l)- )- [ ((i, j, k, m), x)- | (i, xsss) <- inxd l,- (j, xss) <- inxd xsss,- (k, xs) <- inxd xss,- (m, x) <- inxd xs- ]+ fromList l = arrayNestedList bnds l+ where+ (h1, h2, h3) = (head l, head h1, head h2)+ bnds = ((0, 0, 0, 0), (top l, top h1, top h2, top h3)) toList :: Array (i, j, k, m) e -> [[[[e]]]]- toList arr =- let ((_, l1, l2, l3), (_, r1, r2, r3)) = bounds arr- in splitList l1 r1- $ splitList l2 r2- $ splitList l3 r3- $ elems arr+ toList = toNestedList instance- ( Integral i,- Integral j,- Integral k,- Integral m,- Integral n,- Ix i,- Ix j,- Ix k,- Ix m,- Ix n- ) =>+ (Integral i, Integral j, Integral k, Integral m, Integral n, Ix i, Ix j, Ix k, Ix m, Ix n) => IsList (Array (i, j, k, m, n) e) where type Item (Array (i, j, k, m, n) e) = [[[[e]]]] fromList :: [[[[[e]]]]] -> Array (i, j, k, m, n) e- fromList l =+ fromList l = arrayNestedList bnds l+ where+ (h1, h2, h3, h4) = (head l, head h1, head h2, head h3)+ bnds = ((0, 0, 0, 0, 0), (top l, top h1, top h2, top h3, top h4))+ toList :: Array (i, j, k, m, n) e -> [[[[[e]]]]]+ toList = toNestedList++-- | 'ArrayNestedList' class defines methods to convert between+-- nested lists and multi-dimensional (up to 5) 'Array's with any indices,+-- not only 'Integral', using provided range of indices.+class Ix i => ArrayNestedList i e where+ type NestedList i e++ -- | Converts nested list to multi-dimensional 'Array'+ -- Similarly to 'arrayList' function, it does not require to pass index+ -- for each element, only the range of indices.+ arrayNestedList :: (i, i) -> NestedList i e -> Array i e++ -- | Converts multi-dimensional 'Array' to nested list.+ toNestedList :: Array i e -> NestedList i e++instance (Ix i, Ix j) => ArrayNestedList (i, j) e where+ type NestedList (i, j) e = [[e]]+ arrayNestedList ::+ ((i, j), (i, j)) -> [[e]] -> Array (i, j) e+ arrayNestedList bnds@((l1, l2), (r1, r2)) l = array- ( (0, 0, 0, 0, 0),- (top l, top $ h1 l, top $ h2 l, top $ h3 l, top $ h4 l)- )+ bnds+ [ ((i, j), x)+ | xs <- l,+ x <- xs+ | i <- range (l1, r1),+ j <- range (l2, r2)+ ]+ toNestedList :: Array (i, j) e -> [[e]]+ toNestedList arr =+ let ((_, l2), (_, r2)) = bounds arr+ in splitList (l2, r2) $ elems arr++splitList :: Ix i => (i, i) -> [e] -> [[e]]+splitList = split' . rangeSize+ where+ split' _ [] = []+ split' n xs =+ let (part, rest) = splitAt n xs+ in part : split' n rest++instance (Ix i, Ix j, Ix k) => ArrayNestedList (i, j, k) e where+ type NestedList (i, j, k) e = [[[e]]]+ arrayNestedList ::+ ((i, j, k), (i, j, k)) -> [[[e]]] -> Array (i, j, k) e+ arrayNestedList bnds@((l1, l2, l3), (r1, r2, r3)) l =+ array+ bnds+ [ ((i, j, k), x)+ | xss <- l,+ xs <- xss,+ x <- xs+ | i <- range (l1, r1),+ j <- range (l2, r2),+ k <- range (l3, r3)+ ]+ toNestedList :: Array (i, j, k) e -> [[[e]]]+ toNestedList arr =+ let ((_, l2, l3), (_, r2, r3)) = bounds arr+ in splitList (l2, r2)+ $ splitList (l3, r3)+ $ elems arr++instance (Ix i, Ix j, Ix k, Ix m) => ArrayNestedList (i, j, k, m) e where+ type NestedList (i, j, k, m) e = [[[[e]]]]+ arrayNestedList ::+ ((i, j, k, m), (i, j, k, m)) ->+ [[[[e]]]] ->+ Array (i, j, k, m) e+ arrayNestedList bnds@((l1, l2, l3, l4), (r1, r2, r3, r4)) l =+ array+ bnds+ [ ((i, j, k, m), x)+ | xsss <- l,+ xss <- xsss,+ xs <- xss,+ x <- xs+ | i <- range (l1, r1),+ j <- range (l2, r2),+ k <- range (l3, r3),+ m <- range (l4, r4)+ ]+ toNestedList :: Array (i, j, k, m) e -> [[[[e]]]]+ toNestedList arr =+ let ((_, l2, l3, l4), (_, r2, r3, r4)) = bounds arr+ in splitList (l2, r2)+ $ splitList (l3, r3)+ $ splitList (l4, r4)+ $ elems arr++instance (Ix i, Ix j, Ix k, Ix m, Ix n) => ArrayNestedList (i, j, k, m, n) e where+ type NestedList (i, j, k, m, n) e = [[[[[e]]]]]+ arrayNestedList ::+ ((i, j, k, m, n), (i, j, k, m, n)) ->+ [[[[[e]]]]] ->+ Array (i, j, k, m, n) e+ arrayNestedList bnds@((l1, l2, l3, l4, l5), (r1, r2, r3, r4, r5)) l =+ array+ bnds [ ((i, j, k, m, n), x)- | (i, xssss) <- inxd l,- (j, xsss) <- inxd xssss,- (k, xss) <- inxd xsss,- (m, xs) <- inxd xss,- (n, x) <- inxd xs+ | xssss <- l,+ xsss <- xssss,+ xss <- xsss,+ xs <- xss,+ x <- xs+ | i <- range (l1, r1),+ j <- range (l2, r2),+ k <- range (l3, r3),+ m <- range (l4, r4),+ n <- range (l5, r5) ]- toList :: Array (i, j, k, m, n) e -> [[[[[e]]]]]- toList arr =- let ((_, l1, l2, l3, l4), (_, r1, r2, r3, r4)) = bounds arr- in splitList l1 r1- $ splitList l2 r2- $ splitList l3 r3- $ splitList l4 r4+ toNestedList :: Array (i, j, k, m, n) e -> [[[[[e]]]]]+ toNestedList arr =+ let ((_, l2, l3, l4, l5), (_, r2, r3, r4, r5)) = bounds arr+ in splitList (l2, r2)+ $ splitList (l3, r3)+ $ splitList (l4, r4)+ $ splitList (l5, r5) $ elems arr
tests/Main.hs view
@@ -7,6 +7,12 @@ main :: IO () main = hspec do+ describe "array-list" do+ isListTest+ arrayNestedListTest++isListTest :: SpecWith ()+isListTest = describe "IsList" do describe "IsList (Array Int e)" do it "[1,2,3]" $ ([1, 2, 3] :: Array Int Int)@@ -191,6 +197,183 @@ ] ] :: Array (Int, Int, Int, Int, Int) Int+ )+ `shouldBe` [ [ [[[0, 1], [2, 3]], [[4, 5], [6, 7]]],+ [[[8, 9], [10, 11]], [[12, 13], [14, 15]]]+ ],+ [ [[[16, 17], [18, 19]], [[20, 21], [22, 23]]],+ [[[24, 25], [26, 27]], [[28, 29], [30, 31]]]+ ]+ ]++arrayNestedListTest :: SpecWith ()+arrayNestedListTest = describe "ArrayNestedList" do+ describe "ArrayNestedList (Bool,Bool) e" do+ it "[[1, 2], [3, 4]]" $+ ( arrayNestedList+ ((False, False), (True, True))+ [[1, 2], [3, 4]] ::+ Array (Bool, Bool) Int+ )+ `shouldBe` array+ ((False, False), (True, True))+ [ ((False, False), 1),+ ((False, True), 2),+ ((True, False), 3),+ ((True, True), 4)+ ]+ it "toNestedList . arrayNestedList == id" $+ toNestedList+ ( arrayNestedList+ ((False, False), (True, True))+ [[1, 2], [3, 4]] ::+ Array (Bool, Bool) Int+ )+ `shouldBe` [[1, 2], [3, 4]]+ describe "ArrayNestedList (Bool,Bool,Bool) e" do+ it "3D-array" $+ ( arrayNestedList+ ((False, False, False), (True, True, True))+ [ [[1, 2], [3, 4]],+ [[5, 6], [7, 8]]+ ] ::+ Array (Bool, Bool, Bool) Int+ )+ `shouldBe` array+ ((False, False, False), (True, True, True))+ [ ((False, False, False), 1),+ ((False, False, True), 2),+ ((False, True, False), 3),+ ((False, True, True), 4),+ ((True, False, False), 5),+ ((True, False, True), 6),+ ((True, True, False), 7),+ ((True, True, True), 8)+ ]+ it "toNestedList . arrayNestedList == id" $+ toNestedList+ ( arrayNestedList+ ((False, False, False), (True, True, True))+ [ [[1, 2], [3, 4]],+ [[5, 6], [7, 8]]+ ] ::+ Array (Bool, Bool, Bool) Int+ )+ `shouldBe` [ [[1, 2], [3, 4]],+ [[5, 6], [7, 8]]+ ]+ describe "ArrayNestedList (Bool,Bool,Bool,Bool) e" do+ it "4D-array" $+ ( arrayNestedList+ ((False, False, False, False), (True, True, True, True))+ [ [ [[0, 1], [2, 3]],+ [[4, 5], [6, 7]]+ ],+ [ [[8, 9], [10, 11]],+ [[12, 13], [14, 15]]+ ]+ ] ::+ Array (Bool, Bool, Bool, Bool) Int+ )+ `shouldBe` array+ ((False, False, False, False), (True, True, True, True))+ [ ((False, False, False, False), 0),+ ((False, False, False, True), 1),+ ((False, False, True, False), 2),+ ((False, False, True, True), 3),+ ((False, True, False, False), 4),+ ((False, True, False, True), 5),+ ((False, True, True, False), 6),+ ((False, True, True, True), 7),+ ((True, False, False, False), 8),+ ((True, False, False, True), 9),+ ((True, False, True, False), 10),+ ((True, False, True, True), 11),+ ((True, True, False, False), 12),+ ((True, True, False, True), 13),+ ((True, True, True, False), 14),+ ((True, True, True, True), 15)+ ]+ it "toNestedList . arrayNestedList == id" $+ toNestedList+ ( arrayNestedList+ ((False, False, False, False), (True, True, True, True))+ [ [ [[0, 1], [2, 3]],+ [[4, 5], [6, 7]]+ ],+ [ [[8, 9], [10, 11]],+ [[12, 13], [14, 15]]+ ]+ ] ::+ Array (Bool, Bool, Bool, Bool) Int+ )+ `shouldBe` [ [ [[0, 1], [2, 3]],+ [[4, 5], [6, 7]]+ ],+ [ [[8, 9], [10, 11]],+ [[12, 13], [14, 15]]+ ]+ ]+ describe "ArrayNestedList (Bool,Bool,Bool,Bool,Bool) e" do+ it "5D-array" $+ ( arrayNestedList+ ((False, False, False, False, False), (True, True, True, True, True))+ [ [ [[[0, 1], [2, 3]], [[4, 5], [6, 7]]],+ [[[8, 9], [10, 11]], [[12, 13], [14, 15]]]+ ],+ [ [[[16, 17], [18, 19]], [[20, 21], [22, 23]]],+ [[[24, 25], [26, 27]], [[28, 29], [30, 31]]]+ ]+ ] ::+ Array (Bool, Bool, Bool, Bool, Bool) Int+ )+ `shouldBe` array+ ((False, False, False, False, False), (True, True, True, True, True))+ [ ((False, False, False, False, False), 0),+ ((False, False, False, False, True), 1),+ ((False, False, False, True, False), 2),+ ((False, False, False, True, True), 3),+ ((False, False, True, False, False), 4),+ ((False, False, True, False, True), 5),+ ((False, False, True, True, False), 6),+ ((False, False, True, True, True), 7),+ ((False, True, False, False, False), 8),+ ((False, True, False, False, True), 9),+ ((False, True, False, True, False), 10),+ ((False, True, False, True, True), 11),+ ((False, True, True, False, False), 12),+ ((False, True, True, False, True), 13),+ ((False, True, True, True, False), 14),+ ((False, True, True, True, True), 15),+ ((True, False, False, False, False), 16),+ ((True, False, False, False, True), 17),+ ((True, False, False, True, False), 18),+ ((True, False, False, True, True), 19),+ ((True, False, True, False, False), 20),+ ((True, False, True, False, True), 21),+ ((True, False, True, True, False), 22),+ ((True, False, True, True, True), 23),+ ((True, True, False, False, False), 24),+ ((True, True, False, False, True), 25),+ ((True, True, False, True, False), 26),+ ((True, True, False, True, True), 27),+ ((True, True, True, False, False), 28),+ ((True, True, True, False, True), 29),+ ((True, True, True, True, False), 30),+ ((True, True, True, True, True), 31)+ ]+ it "toNestedList . arrayNestedList == id" $+ toNestedList+ ( arrayNestedList+ ((False, False, False, False, False), (True, True, True, True, True))+ [ [ [[[0, 1], [2, 3]], [[4, 5], [6, 7]]],+ [[[8, 9], [10, 11]], [[12, 13], [14, 15]]]+ ],+ [ [[[16, 17], [18, 19]], [[20, 21], [22, 23]]],+ [[[24, 25], [26, 27]], [[28, 29], [30, 31]]]+ ]+ ] ::+ Array (Bool, Bool, Bool, Bool, Bool) Int ) `shouldBe` [ [ [[[0, 1], [2, 3]], [[4, 5], [6, 7]]], [[[8, 9], [10, 11]], [[12, 13], [14, 15]]]