contiguous 0.5.1 → 0.5.2
raw patch · 2 files changed
+343/−59 lines, 2 filesdep +run-stdep ~primitivePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: run-st
Dependency ranges changed: primitive
API changes (from Hackage documentation)
+ Data.Primitive.Contiguous: all :: (Contiguous arr, Element arr a) => (a -> Bool) -> arr a -> Bool
+ Data.Primitive.Contiguous: any :: (Contiguous arr, Element arr a) => (a -> Bool) -> arr a -> Bool
+ Data.Primitive.Contiguous: findIndex :: (Contiguous arr, Element arr a) => (a -> Bool) -> arr a -> Maybe Int
+ Data.Primitive.Contiguous: foldlZipWithM' :: (Contiguous arr1, Contiguous arr2, Element arr1 a, Element arr2 b, Monad m) => (c -> a -> b -> m c) -> c -> arr1 a -> arr2 b -> m c
+ Data.Primitive.Contiguous: foldrZipWith :: (Contiguous arr1, Contiguous arr2, Element arr1 a, Element arr2 b) => (a -> b -> c -> c) -> c -> arr1 a -> arr2 b -> c
+ Data.Primitive.Contiguous: ifoldlM' :: (Contiguous arr, Element arr a, Monad m) => (b -> Int -> a -> m b) -> b -> arr a -> m b
+ Data.Primitive.Contiguous: ifoldlZipWithM' :: (Contiguous arr1, Contiguous arr2, Element arr1 a, Element arr2 b, Monad m) => (Int -> c -> a -> b -> m c) -> c -> arr1 a -> arr2 b -> m c
+ Data.Primitive.Contiguous: ifoldrZipWith :: (Contiguous arr1, Contiguous arr2, Element arr1 a, Element arr2 b) => (Int -> a -> b -> c -> c) -> c -> arr1 a -> arr2 b -> c
+ Data.Primitive.Contiguous: insertAt :: (Contiguous arr, Element arr a) => arr a -> Int -> a -> arr a
+ Data.Primitive.Contiguous: insertSlicing :: (Contiguous arr, Element arr b) => arr b -> Int -> Int -> Int -> b -> arr b
+ Data.Primitive.Contiguous: mapAccum' :: forall arr1 arr2 a b c. (Contiguous arr1, Contiguous arr2, Element arr1 b, Element arr2 c, Monoid a) => (b -> (a, c)) -> arr1 b -> (a, arr2 c)
+ Data.Primitive.Contiguous: mapAccumLM' :: (Contiguous arr1, Contiguous arr2, Element arr1 b, Element arr2 c, Monad m) => (a -> b -> m (a, c)) -> a -> arr1 b -> m (a, arr2 c)
+ Data.Primitive.Contiguous: modifyAt :: (Contiguous arr, Element arr a) => (a -> a) -> arr a -> Int -> arr a
+ Data.Primitive.Contiguous: modifyAt' :: (Contiguous arr, Element arr a) => (a -> a) -> arr a -> Int -> arr a
+ Data.Primitive.Contiguous: modifyAtF :: (Contiguous arr, Element arr a, Functor f) => (a -> f a) -> arr a -> Int -> f (arr a)
+ Data.Primitive.Contiguous: modifyAtF' :: (Contiguous arr, Element arr a, Monad f) => (a -> f a) -> arr a -> Int -> f (arr a)
+ Data.Primitive.Contiguous: quadrupleton :: (Contiguous arr, Element arr a) => a -> a -> a -> a -> arr a
+ Data.Primitive.Contiguous: replaceAt :: (Contiguous arr, Element arr a) => arr a -> Int -> a -> arr a
+ Data.Primitive.Contiguous: run :: Contiguous arr => (forall s. ST s (arr a)) -> arr a
- Data.Primitive.Contiguous: forM_ :: (Contiguous arr, Element arr a, Element arr b, Applicative f) => (a -> f b) -> arr a -> f ()
+ Data.Primitive.Contiguous: forM_ :: (Contiguous arr, Element arr a, Element arr b, Applicative f) => arr a -> (a -> f b) -> f ()
Files
- contiguous.cabal +3/−2
- src/Data/Primitive/Contiguous.hs +340/−57
contiguous.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.0 name: contiguous-version: 0.5.1+version: 0.5.2 homepage: https://github.com/andrewthad/contiguous bug-reports: https://github.com/andrewthad/contiguous/issues author: Andrew Martin@@ -27,9 +27,10 @@ hs-source-dirs: src build-depends: base >=4.11.1.0 && <5- , primitive >= 0.7 && < 0.8+ , primitive >= 0.7.2 && < 0.8 , primitive-unlifted >= 0.1 && < 0.2 , deepseq >= 1.4+ , run-st >= 0.1.1 default-language: Haskell2010 ghc-options: -O2 -Wall
src/Data/Primitive/Contiguous.hs view
@@ -1,14 +1,12 @@-{-# language- BangPatterns- , FlexibleInstances- , LambdaCase- , MagicHash- , RankNTypes- , ScopedTypeVariables- , TypeFamilies- , TypeFamilyDependencies- , UnboxedTuples- #-}+{-# language BangPatterns #-}+{-# language FlexibleInstances #-}+{-# language LambdaCase #-}+{-# language MagicHash #-}+{-# language RankNTypes #-}+{-# language ScopedTypeVariables #-}+{-# language TypeFamilies #-}+{-# language TypeFamilyDependencies #-}+{-# language UnboxedTuples #-} -- | The contiguous typeclass parameterises over a contiguous array type. -- This allows us to have a common API to a number of contiguous@@ -34,6 +32,7 @@ , singleton , doubleton , tripleton+ , quadrupleton , replicate , replicateMutable , generate@@ -42,6 +41,8 @@ , iterateN , iterateMutableN , write+ -- ** Running+ , run -- ** Monadic initialisation , replicateMutableM , generateMutableM@@ -57,7 +58,15 @@ , enumFromMutableN -- ** Concatenation , append+ -- ** Splitting and Splicing+ , insertAt+ , insertSlicing -- * Modifying arrays+ , replaceAt+ , modifyAt+ , modifyAt'+ , modifyAtF+ , modifyAtF' -- ** Permutations , reverse , reverseMutable@@ -98,6 +107,7 @@ , partitionEithers -- ** Searching , find+ , findIndex , elem , maximum , minimum@@ -121,7 +131,15 @@ , ifoldlMap' , ifoldlMap1' , foldlM'+ , ifoldlM' , asum+ , all+ , any+ -- ** Zipping Folds+ , foldrZipWith+ , ifoldrZipWith+ , foldlZipWithM'+ , ifoldlZipWithM' -- * Traversals , traverse@@ -154,6 +172,9 @@ --, postscanl --, ipostscanl + , mapAccum'+ , mapAccumLM'+ -- * Conversions -- ** Lists , fromList@@ -199,25 +220,27 @@ , MutableUnliftedArray ) where -import Prelude hiding (map,foldr,foldMap,traverse,read,filter,replicate,null,reverse,foldl,foldr,zip,zipWith,scanl,(<$),elem,maximum,minimum,mapM,mapM_,sequence,sequence_)+import Control.Monad.Primitive+import Data.Primitive hiding (fromList,fromListN)+import Data.Primitive.Unlifted.Array+import Prelude hiding (map,all,any,foldr,foldMap,traverse,read,filter,replicate,null,reverse,foldl,foldr,zip,zipWith,scanl,(<$),elem,maximum,minimum,mapM,mapM_,sequence,sequence_)+ import Control.Applicative (liftA2) import Control.DeepSeq (NFData) import Control.Monad (when)-import Control.Monad.Primitive import Control.Monad.ST (runST,ST)+import Control.Monad.ST.Run (runPrimArrayST,runSmallArrayST,runUnliftedArrayST,runArrayST) import Data.Bits (xor) import Data.Coerce (coerce) import Data.Kind (Type)-import Data.Primitive hiding (fromList,fromListN)-import Data.Primitive.Unlifted.Array import Data.Primitive.Unlifted.Class (PrimUnlifted)-import Data.Semigroup (Semigroup,(<>),First(..))+import Data.Semigroup (First(..)) import Data.Word (Word8) import GHC.Base (build) import GHC.Exts (MutableArrayArray#,ArrayArray#,Constraint,sizeofByteArray#,sizeofArray#,sizeofArrayArray#,unsafeCoerce#,sameMutableArrayArray#,isTrue#,dataToTag#,Int(..)) -import qualified Control.DeepSeq as DS import qualified Control.Applicative as A+import qualified Control.DeepSeq as DS import qualified Prelude -- | A typeclass that is satisfied by all types. This is used@@ -278,9 +301,17 @@ -- The mutable array should not be used after this conversion. unsafeFreeze :: PrimMonad m => Mutable arr (PrimState m) b -> m (arr b) -- | Turn a mutable array into an immutable one with copying, using a slice of the mutable array.- freeze :: (PrimMonad m, Element arr b) => Mutable arr (PrimState m) b -> Int -> Int -> m (arr b)+ freeze :: (PrimMonad m, Element arr b)+ => Mutable arr (PrimState m) b+ -> Int -- ^ offset into the array+ -> Int -- ^ length of the slice+ -> m (arr b) -- | Copy a slice of an immutable array into a new mutable array.- thaw :: (PrimMonad m, Element arr b) => arr b -> Int -> Int -> m (Mutable arr (PrimState m) b)+ thaw :: (PrimMonad m, Element arr b)+ => arr b+ -> Int -- ^ offset into the array+ -> Int -- ^ length of the slice+ -> m (Mutable arr (PrimState m) b) -- | Copy a slice of an array into a mutable array. copy :: (PrimMonad m, Element arr b) => Mutable arr (PrimState m) b -- ^ destination array@@ -301,16 +332,33 @@ -> m () -- | Clone a slice of an array. clone :: Element arr b- => arr b- -> Int- -> Int+ => arr b -- ^ Array to copy a slice of+ -> Int -- ^ Offset into the array+ -> Int -- ^ Length of the slice -> arr b -- | Clone a slice of a mutable array. cloneMutable :: (PrimMonad m, Element arr b)- => Mutable arr (PrimState m) b- -> Int- -> Int+ => Mutable arr (PrimState m) b -- ^ Array to copy a slice of+ -> Int -- ^ Offset into the array+ -> Int -- ^ Length of the slice -> m (Mutable arr (PrimState m) b)+ -- | Copy a slice of an array an then insert an element into that array.+ --+ -- The default implementation performs a memset which would be unnecessary+ -- except that the garbage collector might trace the uninitialized array.+ insertSlicing :: Element arr b+ => arr b -- ^ array to copy a slice from+ -> Int -- ^ offset into source array+ -> Int -- ^ length of the slice+ -> Int -- ^ index in the output array to insert at+ -> b -- ^ element to insert+ -> arr b+ insertSlicing src off len0 i x = run $ do+ dst <- replicateMutable (len0 + 1) x+ copy dst 0 src off i+ copy dst (i + 1) src (off + i) (len0 - i)+ unsafeFreeze dst+ {-# inline insertSlicing #-} -- | Test the two arrays for equality. equals :: (Element arr b, Eq b) => arr b -> arr b -> Bool -- | Test the two mutable arrays for pointer equality.@@ -326,8 +374,12 @@ doubleton :: Element arr a => a -> a -> arr a -- | Create a tripleton array. tripleton :: Element arr a => a -> a -> a -> arr a+ -- | Create a quadrupleton array.+ quadrupleton :: Element arr a => a -> a -> a -> a -> arr a -- | Reduce the array and all of its elements to WHNF. rnf :: (NFData a, Element arr a) => arr a -> ()+ -- | Run an effectful computation that produces an array.+ run :: (forall s. ST s (arr a)) -> arr a instance Contiguous SmallArray where type Mutable SmallArray = SmallMutableArray@@ -364,6 +416,13 @@ writeSmallArray m 1 b writeSmallArray m 2 c unsafeFreezeSmallArray m+ quadrupleton a b c d = runST $ do+ m <- newSmallArray 4 errorThunk+ writeSmallArray m 0 a+ writeSmallArray m 1 b+ writeSmallArray m 2 c+ writeSmallArray m 3 d+ unsafeFreezeSmallArray m rnf !ary = let !sz = sizeofSmallArray ary go !ix = if ix < sz@@ -380,6 +439,7 @@ copyMutable = copySmallMutableArray replicateMutable = replicateSmallMutableArray resize = resizeSmallArray+ run = runSmallArrayST {-# inline empty #-} {-# inline null #-} {-# inline new #-}@@ -406,7 +466,9 @@ {-# inline singleton #-} {-# inline doubleton #-} {-# inline tripleton #-}+ {-# inline quadrupleton #-} {-# inline rnf #-}+ {-# inline run #-} instance Contiguous PrimArray where type Mutable PrimArray = MutablePrimArray@@ -437,21 +499,35 @@ _ -> False equalsMutable = sameMutablePrimArray rnf (PrimArray !_) = ()- singleton a = runST $ do+ singleton a = runPrimArrayST $ do marr <- newPrimArray 1 writePrimArray marr 0 a unsafeFreezePrimArray marr- doubleton a b = runST $ do+ doubleton a b = runPrimArrayST $ do m <- newPrimArray 2 writePrimArray m 0 a writePrimArray m 1 b unsafeFreezePrimArray m- tripleton a b c = runST $ do+ tripleton a b c = runPrimArrayST $ do m <- newPrimArray 3 writePrimArray m 0 a writePrimArray m 1 b writePrimArray m 2 c unsafeFreezePrimArray m+ quadrupleton a b c d = runPrimArrayST $ do+ m <- newPrimArray 4+ writePrimArray m 0 a+ writePrimArray m 1 b+ writePrimArray m 2 c+ writePrimArray m 3 d+ unsafeFreezePrimArray m+ insertSlicing src off len0 i x = runPrimArrayST $ do+ dst <- new (len0 + 1)+ copy dst 0 src off i+ write dst i x+ copy dst (i + 1) src (off + i) (len0 - i)+ unsafeFreeze dst+ run = runPrimArrayST {-# inline empty #-} {-# inline null #-} {-# inline new #-}@@ -471,6 +547,7 @@ {-# inline copyMutable #-} {-# inline clone #-} {-# inline cloneMutable #-}+ {-# inline insertSlicing #-} {-# inline equals #-} {-# inline equalsMutable #-} {-# inline unlift #-}@@ -478,7 +555,9 @@ {-# inline singleton #-} {-# inline doubleton #-} {-# inline tripleton #-}+ {-# inline quadrupleton #-} {-# inline rnf #-}+ {-# inline run #-} instance Contiguous Array where type Mutable Array = MutableArray@@ -516,16 +595,23 @@ let !(# x #) = indexArray## ary i in DS.rnf x `seq` go (i+1) in go 0- singleton a = runST (newArray 1 a >>= unsafeFreezeArray)- doubleton a b = runST $ do+ singleton a = runArrayST (newArray 1 a >>= unsafeFreezeArray)+ doubleton a b = runArrayST $ do m <- newArray 2 a writeArray m 1 b unsafeFreezeArray m- tripleton a b c = runST $ do+ tripleton a b c = runArrayST $ do m <- newArray 3 a writeArray m 1 b writeArray m 2 c unsafeFreezeArray m+ quadrupleton a b c d = runArrayST $ do+ m <- newArray 4 a+ writeArray m 1 b+ writeArray m 2 c+ writeArray m 3 d+ unsafeFreezeArray m+ run = runArrayST {-# inline empty #-} {-# inline null #-} {-# inline new #-}@@ -552,7 +638,9 @@ {-# inline singleton #-} {-# inline doubleton #-} {-# inline tripleton #-}+ {-# inline quadrupleton #-} {-# inline rnf #-}+ {-# inline run #-} instance Contiguous UnliftedArray where type Mutable UnliftedArray = MutableUnliftedArray@@ -590,16 +678,23 @@ let x = indexUnliftedArray ary i in DS.rnf x `seq` go (i+1) in go 0- singleton a = runST (newUnliftedArray 1 a >>= unsafeFreezeUnliftedArray)- doubleton a b = runST $ do+ singleton a = runUnliftedArrayST (newUnliftedArray 1 a >>= unsafeFreezeUnliftedArray)+ doubleton a b = runUnliftedArrayST $ do m <- newUnliftedArray 2 a writeUnliftedArray m 1 b unsafeFreezeUnliftedArray m- tripleton a b c = runST $ do+ tripleton a b c = runUnliftedArrayST $ do m <- newUnliftedArray 3 a writeUnliftedArray m 1 b writeUnliftedArray m 2 c unsafeFreezeUnliftedArray m+ quadrupleton a b c d = runUnliftedArrayST $ do+ m <- newUnliftedArray 4 a+ writeUnliftedArray m 1 b+ writeUnliftedArray m 2 c+ writeUnliftedArray m 3 d+ unsafeFreezeUnliftedArray m+ run = runUnliftedArrayST {-# inline empty #-} {-# inline null #-} {-# inline new #-}@@ -626,7 +721,9 @@ {-# inline singleton #-} {-# inline doubleton #-} {-# inline tripleton #-}+ {-# inline quadrupleton #-} {-# inline rnf #-}+ {-# inline run #-} errorThunk :: a errorThunk = error "Contiguous typeclass: unitialized element"@@ -662,7 +759,7 @@ -- | Append two arrays. append :: (Contiguous arr, Element arr a) => arr a -> arr a -> arr a-append !a !b = runST $ do+append !a !b = run $ do let !szA = size a let !szB = size b m <- new (szA + szB)@@ -671,9 +768,49 @@ unsafeFreeze m {-# inline append #-} +-- | Insert an element into an array at the given index.+insertAt :: (Contiguous arr, Element arr a) => arr a -> Int -> a -> arr a+insertAt src i x = insertSlicing src 0 (size src) i x++-- | Create a copy of an array except the element at the index is replaced with+-- the given value.+replaceAt :: (Contiguous arr, Element arr a) => arr a -> Int -> a -> arr a+replaceAt src i x = create $ do+ dst <- thaw src 0 (size src)+ write dst i x+ pure dst+{-# inline replaceAt #-}++modifyAt :: (Contiguous arr, Element arr a)+ => (a -> a) -> arr a -> Int -> arr a+modifyAt f src i = replaceAt src i $ f (index src i)+{-# inline modifyAt #-}++-- | Variant of modifyAt that forces the result before installing it in the+-- array.+modifyAt' :: (Contiguous arr, Element arr a)+ => (a -> a) -> arr a -> Int -> arr a+modifyAt' f src i = replaceAt src i $! f (index src i)+{-# inline modifyAt' #-}++modifyAtF :: (Contiguous arr, Element arr a, Functor f)+ => (a -> f a) -> arr a -> Int -> f (arr a)+modifyAtF f src i = replaceAt src i <$> f (index src i)+{-# inline modifyAtF #-}++-- | Variant of modifyAtF that forces the result before installing it in the+-- array. Note that this requires 'Monad' rather than 'Functor'.+modifyAtF' :: (Contiguous arr, Element arr a, Monad f)+ => (a -> f a) -> arr a -> Int -> f (arr a)+modifyAtF' f src i = do+ !r <- f (index src i)+ let !dst = replaceAt src i r+ pure dst+{-# inline modifyAtF' #-}+ -- | Map over the elements of an array with the index. imap :: (Contiguous arr1, Element arr1 b, Contiguous arr2, Element arr2 c) => (Int -> b -> c) -> arr1 b -> arr2 c-imap f a = runST $ do+imap f a = run $ do mb <- new (size a) let go !i | i == size a = pure ()@@ -690,7 +827,7 @@ -- Note that because a new array must be created, the resulting -- array type can be /different/ than the original. imap' :: (Contiguous arr1, Element arr1 b, Contiguous arr2, Element arr2 c) => (Int -> b -> c) -> arr1 b -> arr2 c-imap' f a = runST $ do+imap' f a = run $ do mb <- new (size a) let go !i | i == size a = pure ()@@ -708,7 +845,7 @@ -- Note that because a new array must be created, the resulting -- array type can be /different/ than the original. map :: (Contiguous arr1, Element arr1 b, Contiguous arr2, Element arr2 c) => (b -> c) -> arr1 b -> arr2 c-map f a = runST $ do+map f a = run $ do mb <- new (size a) let go !i | i == size a = pure ()@@ -725,7 +862,7 @@ -- Note that because a new array must be created, the resulting -- array type can be /different/ than the original. map' :: (Contiguous arr1, Element arr1 b, Contiguous arr2, Element arr2 c) => (b -> c) -> arr1 b -> arr2 c-map' f a = runST $ do+map' f a = run $ do mb <- new (size a) let go !i | i == size a = pure ()@@ -881,6 +1018,19 @@ in go 0 z0 {-# inline foldlM' #-} +-- | Strict left monadic fold over the elements of an array.+ifoldlM' :: (Contiguous arr, Element arr a, Monad m) => (b -> Int -> a -> m b) -> b -> arr a -> m b+ifoldlM' f z0 = \arr ->+ let !sz = size arr+ go !ix !acc1 = if ix < sz+ then do+ let (# x #) = index# arr ix+ acc2 <- f acc1 ix x+ go (ix + 1) acc2+ else pure acc1+ in go 0 z0+{-# inline ifoldlM' #-}+ -- | Drop elements that do not satisfy the predicate. filter :: (Contiguous arr, Element arr a) => (a -> Bool)@@ -895,7 +1045,7 @@ => (Int -> a -> Bool) -> arr a -> arr a-ifilter p arr = runST $ do+ifilter p arr = run $ do marr :: MutablePrimArray s Word8 <- newPrimArray sz let go1 :: Int -> Int -> ST s Int go1 !ix !numTrue = if ix < sz@@ -933,10 +1083,10 @@ => (a -> Maybe b) -> arr1 a -> arr2 b-mapMaybe f arr = runST $ do+mapMaybe f arr = run $ do let !sz = size arr let go :: Int -> Int -> [b] -> ST s ([b],Int)- go !ix !numJusts justs = if ix < sz+ go !ix !numJusts !justs = if ix < sz then do atIx <- indexM arr ix case f atIx of@@ -961,15 +1111,8 @@ catMaybes = mapMaybe id {-# inline catMaybes #-} -thawPrimArray :: (PrimMonad m, Prim a) => PrimArray a -> Int -> Int -> m (MutablePrimArray (PrimState m) a)-thawPrimArray !arr !off !len = do- marr <- newPrimArray len- copyPrimArray marr 0 arr off len- pure marr-{-# inline thawPrimArray #-}- clonePrimArrayShim :: Prim a => PrimArray a -> Int -> Int -> PrimArray a-clonePrimArrayShim !arr !off !len = runST $ do+clonePrimArrayShim !arr !off !len = runPrimArrayST $ do marr <- newPrimArray len copyPrimArray marr 0 arr off len unsafeFreezePrimArray marr@@ -1257,6 +1400,49 @@ for_ = flip traverse_ {-# inline for_ #-} +-- | Monadic accumulating strict left fold over the elements on an+-- array.+mapAccumLM' ::+ ( Contiguous arr1+ , Contiguous arr2+ , Element arr1 b+ , Element arr2 c+ , Monad m+ ) => (a -> b -> m (a, c)) -> a -> arr1 b -> m (a, arr2 c)+{-# inline mapAccumLM' #-}+mapAccumLM' f a0 src = go 0 [] a0 where+ !sz = size src+ go !ix !xs !acc = if ix < sz+ then do+ (!acc',!x) <- f acc (index src ix)+ go (ix + 1) (x : xs) acc'+ else+ let !xs' = unsafeFromListReverseN sz xs+ in pure (acc,xs')++mapAccum' :: forall arr1 arr2 a b c.+ ( Contiguous arr1+ , Contiguous arr2+ , Element arr1 b+ , Element arr2 c+ , Monoid a+ ) => (b -> (a, c)) -> arr1 b -> (a, arr2 c)+{-# inline mapAccum' #-}+mapAccum' f !src = runST $ do+ dst <- new sz+ acc <- go 0 dst mempty+ dst' <- unsafeFreeze dst+ pure (acc,dst')+ where+ !sz = size src+ go :: Int -> Mutable arr2 s c -> a -> ST s a+ go !ix !dst !accA = if ix < sz+ then do+ let (!accB,!x) = f (index src ix)+ write dst ix x+ go (ix + 1) dst (accA <> accB)+ else pure accA+ -- | Map each element of a structure to a monadic action, -- evaluate these actions from left to right, and collect -- the results. for a version that ignores the results see@@ -1305,10 +1491,10 @@ -- | 'forM_' is 'mapM_' with its arguments flipped. For a version that -- doesn't ignore its results, see 'forM'. forM_ :: (Contiguous arr, Element arr a, Element arr b, Applicative f)- => (a -> f b)- -> arr a+ => arr a+ -> (a -> f b) -> f ()-forM_ = traverse_+forM_ = flip traverse_ {-# inline forM_ #-} -- | Evaluate each action in the structure from left to right@@ -1357,7 +1543,7 @@ {-# inline generate #-} -- | Construct an array of the given length by applying--- the monadic actino to each index.+-- the monadic action to each index. generateM :: (Contiguous arr, Element arr a, Monad m) => Int -> (Int -> m a)@@ -1453,7 +1639,7 @@ create :: (Contiguous arr, Element arr a) => (forall s. ST s (Mutable arr s a)) -> arr a-create x = runST (unsafeFreeze =<< x)+create x = run (unsafeFreeze =<< x) {-# inline create #-} -- | Execute the monadic action and freeze the resulting array.@@ -1686,7 +1872,7 @@ reverse :: (Contiguous arr, Element arr a) => arr a -> arr a-reverse arr = runST $ do+reverse arr = run $ do marr <- new sz copy marr 0 arr 0 sz reverseMutable marr@@ -1796,7 +1982,7 @@ -- | 'find' takes a predicate and an array, and returns the leftmost -- element of the array matching the prediate, or 'Nothing' if there--- is no such predicate.+-- is no such element. find :: (Contiguous arr, Element arr a) => (a -> Bool) -> arr a@@ -1804,6 +1990,20 @@ find p = coerce . (foldMap (\x -> if p x then Just (First x) else Nothing)) {-# inline find #-} +-- | 'findIndex' takes a predicate and an array, and returns the index of+-- the leftmost element of the array matching the prediate, or 'Nothing'+-- if there is no such element.+findIndex :: (Contiguous arr, Element arr a)+ => (a -> Bool)+ -> arr a+ -> Maybe Int+findIndex p xs = loop 0+ where+ loop i+ | i < size xs = if p (index xs i) then Just i else loop (i + 1)+ | otherwise = Nothing+{-# inline findIndex #-}+ -- | Swap the elements of the mutable array at the given indices. swap :: (Contiguous arr, Element arr a, PrimMonad m) => Mutable arr (PrimState m) a@@ -2089,6 +2289,82 @@ pure marr {-# inline izipWith #-} +-- | Variant of 'zipWith' that accepts an accumulator, performing a lazy+-- right fold over both arrays.+foldrZipWith ::+ ( Contiguous arr1+ , Contiguous arr2+ , Element arr1 a+ , Element arr2 b+ ) => (a -> b -> c -> c)+ -> c+ -> arr1 a+ -> arr2 b+ -> c+foldrZipWith f = ifoldrZipWith (\_ x y c -> f x y c)+{-# inline foldrZipWith #-}++-- | Variant of 'zipWith' that accepts an accumulator, performing a strict+-- left monadic fold over both arrays.+foldlZipWithM' ::+ ( Contiguous arr1+ , Contiguous arr2+ , Element arr1 a+ , Element arr2 b+ , Monad m+ ) => (c -> a -> b -> m c)+ -> c+ -> arr1 a+ -> arr2 b+ -> m c+foldlZipWithM' f = ifoldlZipWithM' (\_ x y c -> f x y c)+{-# inline foldlZipWithM' #-}++-- | Variant of 'foldrZipWith' that provides the index of each pair of elements.+ifoldrZipWith ::+ ( Contiguous arr1+ , Contiguous arr2+ , Element arr1 a+ , Element arr2 b+ ) => (Int -> a -> b -> c -> c)+ -> c+ -> arr1 a+ -> arr2 b+ -> c+ifoldrZipWith f z = \arr1 arr2 ->+ let !sz = min (size arr1) (size arr2)+ go !ix = if sz > ix+ then case index# arr1 ix of+ (# x #) -> case index# arr2 ix of+ (# y #) -> f ix x y (go (ix + 1))+ else z+ in go 0+{-# inline ifoldrZipWith #-}++-- | Variant of 'foldlZipWithM\'' that provides the index of each pair of elements.+ifoldlZipWithM' ::+ ( Contiguous arr1+ , Contiguous arr2+ , Element arr1 a+ , Element arr2 b+ , Monad m+ ) => (Int -> c -> a -> b -> m c)+ -> c+ -> arr1 a+ -> arr2 b+ -> m c+ifoldlZipWithM' f z = \arr1 arr2 ->+ let !sz = min (size arr1) (size arr2)+ go !ix !acc = if sz > ix+ then case index# arr1 ix of+ (# x #) -> case index# arr2 ix of+ (# y #) -> do+ acc' <- f ix acc x y+ go (ix + 1) acc'+ else pure acc+ in go 0 z+{-# inline ifoldlZipWithM' #-}+ -- | 'zip' takes two arrays and returns an array of -- corresponding pairs. --@@ -2153,3 +2429,10 @@ !szxs = size xs {-# inline ap #-} +all :: (Contiguous arr, Element arr a) => (a -> Bool) -> arr a -> Bool+all f = foldr (\x acc -> f x && acc) True+{-# inline all #-}++any :: (Contiguous arr, Element arr a) => (a -> Bool) -> arr a -> Bool+any f = foldr (\x acc -> f x || acc) False+{-# inline any #-}