packages feed

array-chunks 0.1.1.0 → 0.1.2.0

raw patch · 4 files changed

+180/−17 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Chunks: doubleton :: a -> a -> Chunks a
+ Data.Chunks: index :: Chunks a -> Int -> Maybe a
+ Data.Chunks: map' :: (a -> b) -> Chunks a -> SmallArray b
+ Data.Chunks: null :: Chunks a -> Bool
+ Data.Chunks: octupleton :: a -> a -> a -> a -> a -> a -> a -> a -> Chunks a
+ Data.Chunks: quadrupleton :: a -> a -> a -> a -> Chunks a
+ Data.Chunks: quintupleton :: a -> a -> a -> a -> a -> Chunks a
+ Data.Chunks: septupleton :: a -> a -> a -> a -> a -> a -> a -> Chunks a
+ Data.Chunks: sextupleton :: a -> a -> a -> a -> a -> a -> Chunks a
+ Data.Chunks: singleton :: a -> Chunks a
+ Data.Chunks: tripleton :: a -> a -> a -> Chunks a

Files

CHANGELOG.md view
@@ -1,5 +1,13 @@ # Revision history for array-chunks +## 0.1.2.0 -- 2020-11-18++* Add `index`.+* Add `singleton`, `doubleton`, `tripleton`, `quadrupleton`,+  `quintupleton`, `sextupleton`, `septupleton`, `octupleton`.+* Add `map'`, which converts to `SmallArray` while mapping over+  the elements.+ ## 0.1.1.0 -- 2019-09-12  * Add `copy`, `copyReverse`, `concat`, and `concatReverse`.
array-chunks.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: array-chunks-version: 0.1.1.0+version: 0.1.2.0 synopsis: Lists of chunks description:   Lists of chunks. This is similar to the Cons List provided
src/Data/Chunks.hs view
@@ -6,15 +6,29 @@  module Data.Chunks   ( Chunks(..)+  , null   , reverse   , reverseOnto   , copy   , copyReverse   , concat   , concatReverse+    -- * Indexing+  , index+    -- * Traversals+  , map'+    -- * Construction+  , singleton+  , doubleton+  , tripleton+  , quadrupleton+  , quintupleton+  , sextupleton+  , septupleton+  , octupleton   ) where -import Prelude hiding (reverse,concat)+import Prelude hiding (reverse,concat,null)  import Data.Primitive (SmallArray(..),SmallMutableArray(..)) import GHC.Exts (IsList,Int#,State#,SmallMutableArray#,Int(I#),(+#),(-#))@@ -45,6 +59,26 @@   toList = chunksToSmallArrayList   fromList xs = F.foldr ChunksCons ChunksNil xs +-- | Are there any elements in the chunked list?+null :: Chunks a -> Bool+null = go where+  go ChunksNil = True+  go (ChunksCons x xs) = case PM.sizeofSmallArray x of+    0 -> go xs+    _ -> False++-- | Indexing into the chunked list, returning @Nothing@ if there+-- are not enough elements.+index :: Chunks a -> Int -> Maybe a+index cs0 !ix0 = go cs0 ix0 where+  go ChunksNil !_ = Nothing+  go (ChunksCons x xs) !ix =+    let !len = PM.sizeofSmallArray x in+    if ix < len+      then case PM.indexSmallArray## x ix of+        (# v #) -> Just v+      else go xs (ix - len)+ chunksToSmallArrayList :: Chunks a -> [SmallArray a] chunksToSmallArrayList ChunksNil = [] chunksToSmallArrayList (ChunksCons x xs) =@@ -52,29 +86,22 @@  eqChunks :: Eq a => Chunks a -> Chunks a -> Bool eqChunks ChunksNil cs = allEmpty cs-eqChunks (ChunksCons x xs) cs = eqChunksConsLeft x 0 (PM.sizeofSmallArray x) xs cs+eqChunks (ChunksCons x xs) cs = eqChunksCons x 0 (PM.sizeofSmallArray x) xs cs --- The first argument chunk belongs to the second argument chunks.+-- The first argument chunk belongs to the first argument chunks. -- It is its head. -eqChunksConsLeft :: Eq a => SmallArray a -> Int -> Int -> Chunks a -> Chunks a -> Bool-eqChunksConsLeft !_ !_ !len xs ChunksNil = case len of+eqChunksCons :: Eq a => SmallArray a -> Int -> Int -> Chunks a -> Chunks a -> Bool+eqChunksCons !_ !_ !len xs ChunksNil = case len of   0 -> allEmpty xs   _ -> False-eqChunksConsLeft x !off !len xs (ChunksCons y ys) =+eqChunksCons x !off !len xs (ChunksCons y ys) =   eqChunksConsBoth x off len y 0 (PM.sizeofSmallArray y) xs ys -eqChunksConsRight :: Eq a => Chunks a -> SmallArray a -> Int -> Int -> Chunks a -> Bool-eqChunksConsRight ChunksNil !_ !_ !len ys = case len of-  0 -> allEmpty ys-  _ -> False-eqChunksConsRight (ChunksCons x xs) !y !off !len ys =-  eqChunksConsBoth x 0 (PM.sizeofSmallArray x) y off len xs ys- eqChunksConsBoth :: Eq a => SmallArray a -> Int -> Int -> SmallArray a -> Int -> Int -> Chunks a -> Chunks a -> Bool eqChunksConsBoth !xh !xoff !xlen !yh !yoff !ylen !xt !yt = case compare xlen ylen of-  LT -> eqRange xh xoff yh yoff xlen && eqChunksConsRight xt yh xlen (ylen - xlen) yt-  GT -> eqRange xh xoff yh yoff ylen && eqChunksConsLeft xh ylen (xlen - ylen) xt yt-  EQ -> xh == yh && eqChunks xt yt+  LT -> eqRange xh xoff yh yoff xlen && eqChunksCons yh (yoff + xlen) (ylen - xlen) yt xt+  GT -> eqRange xh xoff yh yoff ylen && eqChunksCons xh (xoff + ylen) (xlen - ylen) xt yt+  EQ -> eqRange xh xoff yh yoff xlen && eqChunks xt yt  eqRange :: Eq a => SmallArray a -> Int -> SmallArray a -> Int -> Int -> Bool eqRange !xs !xoff !ys !yoff !len@@ -244,3 +271,117 @@ errorThunk :: a {-# noinline errorThunk #-} errorThunk = error "Data.Chunks: mistake"++-- | Mapping over chunks is a little unusual in that the result+-- is just a 'SmallArray'.+map' :: (a -> b) -> Chunks a -> SmallArray b+{-# inline map' #-}+map' f cs = runSmallArrayST $ do+  dst <- PM.newSmallArray len errorThunk+  !_ <- F.foldlM+    ( \ !ix a -> do+      let !b = f a+      PM.writeSmallArray dst ix b+      pure (ix + 1)+    ) 0 cs+  PM.unsafeFreezeSmallArray dst+  where+  !len = chunksLength cs++-- | Create chunks with 1 element.+singleton :: a -> Chunks a+{-# inline singleton #-}+singleton a = ChunksCons+  ( runSmallArrayST (PM.newSmallArray 1 a >>= PM.unsafeFreezeSmallArray)+  ) ChunksNil++-- | Create chunks with 2 elements.+doubleton :: a -> a -> Chunks a+{-# inline doubleton #-}+doubleton a b = ChunksCons+  ( runSmallArrayST $ do+      dst <- PM.newSmallArray 2 a+      PM.writeSmallArray dst 1 b+      PM.unsafeFreezeSmallArray dst+  ) ChunksNil++-- | Create chunks with 3 elements.+tripleton :: a -> a -> a -> Chunks a+{-# inline tripleton #-}+tripleton a b c = ChunksCons+  ( runSmallArrayST $ do+      dst <- PM.newSmallArray 3 a+      PM.writeSmallArray dst 1 b+      PM.writeSmallArray dst 2 c+      PM.unsafeFreezeSmallArray dst+  ) ChunksNil++-- | Create chunks with 4 elements.+quadrupleton :: a -> a -> a -> a -> Chunks a+{-# inline quadrupleton #-}+quadrupleton a b c d = ChunksCons+  ( runSmallArrayST $ do+      dst <- PM.newSmallArray 4 a+      PM.writeSmallArray dst 1 b+      PM.writeSmallArray dst 2 c+      PM.writeSmallArray dst 3 d+      PM.unsafeFreezeSmallArray dst+  ) ChunksNil++-- | Create chunks with 5 elements.+quintupleton :: a -> a -> a -> a -> a -> Chunks a+{-# inline quintupleton #-}+quintupleton a b c d e = ChunksCons+  ( runSmallArrayST $ do+      dst <- PM.newSmallArray 5 a+      PM.writeSmallArray dst 1 b+      PM.writeSmallArray dst 2 c+      PM.writeSmallArray dst 3 d+      PM.writeSmallArray dst 4 e+      PM.unsafeFreezeSmallArray dst+  ) ChunksNil++-- | Create chunks with 6 elements.+sextupleton :: a -> a -> a -> a -> a -> a -> Chunks a+{-# inline sextupleton #-}+sextupleton a b c d e f = ChunksCons+  ( runSmallArrayST $ do+      dst <- PM.newSmallArray 6 a+      PM.writeSmallArray dst 1 b+      PM.writeSmallArray dst 2 c+      PM.writeSmallArray dst 3 d+      PM.writeSmallArray dst 4 e+      PM.writeSmallArray dst 5 f+      PM.unsafeFreezeSmallArray dst+  ) ChunksNil++-- | Create chunks with 7 elements.+septupleton :: a -> a -> a -> a -> a -> a -> a -> Chunks a+{-# inline septupleton #-}+septupleton a b c d e f g = ChunksCons+  ( runSmallArrayST $ do+      dst <- PM.newSmallArray 7 a+      PM.writeSmallArray dst 1 b+      PM.writeSmallArray dst 2 c+      PM.writeSmallArray dst 3 d+      PM.writeSmallArray dst 4 e+      PM.writeSmallArray dst 5 f+      PM.writeSmallArray dst 6 g+      PM.unsafeFreezeSmallArray dst+  ) ChunksNil++-- | Create chunks with 8 elements.+octupleton :: a -> a -> a -> a -> a -> a -> a -> a -> Chunks a+{-# inline octupleton #-}+octupleton a b c d e f g h = ChunksCons+  ( runSmallArrayST $ do+      dst <- PM.newSmallArray 8 a+      PM.writeSmallArray dst 1 b+      PM.writeSmallArray dst 2 c+      PM.writeSmallArray dst 3 d+      PM.writeSmallArray dst 4 e+      PM.writeSmallArray dst 5 f+      PM.writeSmallArray dst 6 g+      PM.writeSmallArray dst 7 h+      PM.unsafeFreezeSmallArray dst+  ) ChunksNil
test/Main.hs view
@@ -8,10 +8,12 @@ import Data.Chunks (Chunks(ChunksCons,ChunksNil)) import Data.Primitive (SmallArray) import Data.Proxy (Proxy(Proxy))+import GHC.Exts (fromList) import Test.QuickCheck (Arbitrary,Gen,(===)) import Test.QuickCheck.Classes (eqLaws,semigroupLaws) import Test.QuickCheck.Classes (monoidLaws,isListLaws,foldableLaws) import Test.Tasty (defaultMain,testGroup,TestTree)+import Test.Tasty.HUnit (testCase,(@=?)) import qualified Data.Chunks as C import qualified Data.Foldable as F import qualified Data.List as L@@ -36,6 +38,18 @@       Exts.toList (mconcat (L.reverse (Exts.toList cs)))       ===       Exts.toList (C.concatReverse cs)+  , testCase "eq-A" $+      fromList [fromList [5 :: Integer],fromList [6 :: Integer]]+      @=?+      (fromList [fromList [5 :: Integer,6]] :: Chunks Integer)+  , testCase "eq-B" $+      fromList [fromList [],fromList [5 :: Integer],fromList [6 :: Integer]]+      @=?+      (fromList [fromList [5 :: Integer,6]] :: Chunks Integer)+  , testCase "eq-C" $+      fromList [fromList [],fromList [5 :: Integer],fromList [6 :: Integer]]+      @=?+      (fromList [fromList [5 :: Integer,6],fromList []] :: Chunks Integer)   ]  lawsToTest :: QCC.Laws -> TestTree