{-# LANGUAGE BangPatterns #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module : Data.Massiv.Array.Manifest.List -- Copyright : (c) Alexey Kuleshevich 2018-2021 -- License : BSD3 -- Maintainer : Alexey Kuleshevich -- Stability : experimental -- Portability : non-portable -- module Data.Massiv.Array.Manifest.List ( -- ** List fromList , fromListsM , fromLists' , toList , toLists , toLists2 , toLists3 , toLists4 ) where import Data.Massiv.Array.Manifest.Internal import Data.Massiv.Array.Ops.Fold (foldrInner) import Data.Massiv.Array.Ops.Fold.Internal (foldrFB) import Data.Massiv.Core.Common import Data.Massiv.Core.List import qualified GHC.Exts as GHC (build, IsList(..)) -- | Convert a flat list into a vector -- -- @since 0.1.0 fromList :: forall r e. Manifest r e => Comp -- ^ Computation startegy to use -> [e] -- ^ Flat list -> Vector r e fromList = fromLists' {-# INLINE fromList #-} -- | /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. -- -- ==== __Examples__ -- -- >>> import Data.Massiv.Array as A -- >>> fromListsM Seq [[1,2,3],[4,5,6]] :: Maybe (Array U Ix2 Int) -- Just (Array U Seq (Sz (2 :. 3)) -- [ [ 1, 2, 3 ] -- , [ 4, 5, 6 ] -- ] -- ) -- -- >>> fromListsM Par [[[1,2,3]],[[4,5,6]]] :: Maybe (Array U Ix3 Int) -- Just (Array U Par (Sz (2 :> 1 :. 3)) -- [ [ [ 1, 2, 3 ] -- ] -- , [ [ 4, 5, 6 ] -- ] -- ] -- ) -- -- Elements of a boxed array could be lists themselves if necessary, but cannot be ragged: -- -- >>> fromListsM Seq [[[1,2,3]],[[4,5]]] :: Maybe (Array B Ix2 [Int]) -- Just (Array B Seq (Sz (2 :. 1)) -- [ [ [1,2,3] ] -- , [ [4,5] ] -- ] -- ) -- >>> fromListsM Seq [[[1,2,3]],[[4,5]]] :: Maybe (Array B Ix3 Integer) -- Nothing -- >>> fromListsM Seq [[[1,2,3]],[[4,5,6],[7,8,9]]] :: IO (Array B Ix3 Integer) -- *** Exception: DimTooLongException for (Dim 2): expected (Sz1 1), got (Sz1 2) -- >>> fromListsM Seq [[1,2,3,4],[5,6,7]] :: IO (Matrix B Integer) -- *** Exception: DimTooShortException for (Dim 1): expected (Sz1 4), got (Sz1 3) -- -- @since 0.3.0 fromListsM :: forall r ix e m. (Ragged L ix e, Manifest r e, MonadThrow m) => Comp -> [ListItem ix e] -> m (Array r ix e) fromListsM comp = fromRaggedArrayM . setComp comp . fromListToListArray {-# INLINE fromListsM #-} fromListToListArray :: forall ix e. GHC.IsList (Array L ix e) => [ListItem ix e] -> Array L ix e fromListToListArray = GHC.fromList {-# INLINE fromListToListArray #-} -- | Same as `fromListsM`, but will throw an error on irregular shaped lists. -- -- __Note__: This function is the same as if you would turn on @{-\# LANGUAGE OverloadedLists #-}@ -- extension. For that reason you can also use `GHC.Exts.fromList`. -- -- prop> \xs -> fromLists' Seq xs == (fromList Seq xs :: Vector P Int) -- -- ====__Examples__ -- -- Convert a list of lists into a 2D Array -- -- >>> import Data.Massiv.Array as A -- >>> fromLists' Seq [[1,2,3],[4,5,6]] :: Array U Ix2 Int -- Array U Seq (Sz (2 :. 3)) -- [ [ 1, 2, 3 ] -- , [ 4, 5, 6 ] -- ] -- -- Above example implemented using GHC's `OverloadedLists` extension: -- -- >>> :set -XOverloadedLists -- >>> [[1,2,3],[4,5,6]] :: Array U Ix2 Int -- Array U Seq (Sz (2 :. 3)) -- [ [ 1, 2, 3 ] -- , [ 4, 5, 6 ] -- ] -- -- @since 0.1.0 fromLists' :: forall r ix e. (HasCallStack, Ragged L ix e, Manifest r e) => Comp -- ^ Computation startegy to use -> [ListItem ix e] -- ^ Nested list -> Array r ix e fromLists' comp = fromRaggedArray' . setComp comp . fromListToListArray {-# INLINE fromLists' #-} -- | Convert any array to a flat list. -- -- ==== __Examples__ -- -- >>> import Data.Massiv.Array -- >>> toList $ makeArrayR U Seq (Sz (2 :. 3)) fromIx2 -- [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)] -- -- @since 0.1.0 toList :: (Index ix, Source r e) => Array r ix e -> [e] toList !arr = GHC.build (\ c n -> foldrFB c n arr) {-# INLINE toList #-} -- | /O(n)/ - Convert an array into a nested list. Number of array dimensions 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 `GHC.Exts.toList`. -- -- ==== __Examples__ -- -- >>> import Data.Massiv.Array -- >>> arr = makeArrayR U Seq (Sz (2 :> 1 :. 3)) id -- >>> arr -- Array U Seq (Sz (2 :> 1 :. 3)) -- [ [ [ 0 :> 0 :. 0, 0 :> 0 :. 1, 0 :> 0 :. 2 ] -- ] -- , [ [ 1 :> 0 :. 0, 1 :> 0 :. 1, 1 :> 0 :. 2 ] -- ] -- ] -- >>> toLists arr -- [[[0 :> 0 :. 0,0 :> 0 :. 1,0 :> 0 :. 2]],[[1 :> 0 :. 0,1 :> 0 :. 1,1 :> 0 :. 2]]] -- -- @since 0.1.0 toLists :: (Ragged L ix e, Shape r ix, Source r e) => Array r ix e -- ^ Array to be converted to nested lists -> [ListItem ix e] toLists = GHC.toList . toListArray {-# INLINE toLists #-} -- | Convert an array with at least 2 dimensions into a list of lists. Inner dimensions will get -- flattened. -- -- ==== __Examples__ -- -- >>> import Data.Massiv.Array -- >>> toLists2 $ makeArrayR U Seq (Sz2 2 3) fromIx2 -- [[(0,0),(0,1),(0,2)],[(1,0),(1,1),(1,2)]] -- >>> toLists2 $ makeArrayR U Seq (Sz3 2 1 3) fromIx3 -- [[(0,0,0),(0,0,1),(0,0,2)],[(1,0,0),(1,0,1),(1,0,2)]] -- -- @since 0.1.0 toLists2 :: (Source r e, Index ix, Index (Lower ix)) => Array r ix e -> [[e]] toLists2 = toList . foldrInner (:) [] {-# INLINE toLists2 #-} -- | Convert an array with at least 3 dimensions into a 3 deep nested list. Inner dimensions will -- get flattened. -- -- @since 0.1.0 toLists3 :: (Source r e, Index ix, Index (Lower ix), Index (Lower (Lower ix))) => Array r ix e -> [[[e]]] toLists3 = toList . foldrInner (:) [] . foldrInner (:) [] {-# INLINE toLists3 #-} -- | Convert an array with at least 4 dimensions into a 4 deep nested list. Inner dimensions will -- get flattened. -- -- @since 0.1.0 toLists4 :: ( Source r e , Index ix , Index (Lower ix) , Index (Lower (Lower ix)) , Index (Lower (Lower (Lower ix))) ) => Array r ix e -> [[[[e]]]] toLists4 = toList . foldrInner (:) [] . foldrInner (:) [] . foldrInner (:) [] {-# INLINE toLists4 #-} -- $setup -- >>> import Data.Massiv.Array as A