diff --git a/contiguous.cabal b/contiguous.cabal
--- a/contiguous.cabal
+++ b/contiguous.cabal
@@ -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
 
diff --git a/src/Data/Primitive/Contiguous.hs b/src/Data/Primitive/Contiguous.hs
--- a/src/Data/Primitive/Contiguous.hs
+++ b/src/Data/Primitive/Contiguous.hs
@@ -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 #-}
