diff --git a/src/Data/Vector/Circular.hs b/src/Data/Vector/Circular.hs
--- a/src/Data/Vector/Circular.hs
+++ b/src/Data/Vector/Circular.hs
@@ -9,557 +9,1741 @@
   , ScopedTypeVariables
   , TemplateHaskell
   , TypeApplications
-#-}
-
-module Data.Vector.Circular
-  ( -- * Types
-    CircularVector(..)
-
-    -- * Construction
-  , singleton
-  , toVector
-  , toNonEmptyVector
-  , fromVector
-  , unsafeFromVector
-  , fromList
-  , fromListN
-  , unsafeFromList
-  , unsafeFromListN
-  , vec
-
-    -- * Rotation
-  , rotateLeft
-  , rotateRight
-
-    -- * Comparisons
-  , equivalent
-  , canonise
-  , leastRotation
-
-    -- * Folds
-  , Data.Vector.Circular.foldMap
-  , Data.Vector.Circular.foldMap'
-  , Data.Vector.Circular.foldr
-  , Data.Vector.Circular.foldl
-  , Data.Vector.Circular.foldr'
-  , Data.Vector.Circular.foldl'
-  , Data.Vector.Circular.foldr1
-  , Data.Vector.Circular.foldl1
-  , Data.Vector.Circular.foldMap1
-  , Data.Vector.Circular.foldMap1'
-  , Data.Vector.Circular.toNonEmpty
-
-    -- * Specialized folds
-  , Data.Vector.Circular.all
-  , Data.Vector.Circular.any
-  , Data.Vector.Circular.and
-  , Data.Vector.Circular.or
-  , Data.Vector.Circular.sum
-  , Data.Vector.Circular.product
-  , Data.Vector.Circular.maximum
-  , Data.Vector.Circular.maximumBy
-  , Data.Vector.Circular.minimum
-  , Data.Vector.Circular.minimumBy
-  , rotateToMinimumBy
-  , rotateToMaximumBy
-
-    -- * Indexing
-  , index
-  , head
-  , last
-
-    -- * Zipping
-  , Data.Vector.Circular.zipWith
-  , Data.Vector.Circular.zipWith3
-  , Data.Vector.Circular.zip
-  , Data.Vector.Circular.zip3
-
-    -- * Permutations
-  , Data.Vector.Circular.reverse
-  ) where
-
-import Control.Monad (when, forM_)
-import Control.Monad.ST (ST, runST)
-import Control.DeepSeq
-#if MIN_VERSION_base(4,13,0)
-import Data.Foldable (foldMap')
-#endif /* MIN_VERSION_base(4,13,0) */
-import Data.List.NonEmpty (NonEmpty)
-import Data.Primitive.MutVar
-import Data.Semigroup.Foldable.Class (Foldable1)
-import Data.Monoid (All(..))
-import Data.Vector (Vector)
-import Data.Vector.NonEmpty (NonEmptyVector)
-import GHC.Base (modInt)
-import GHC.Generics (Generic)
-import Prelude hiding (head, length, last)
-import Language.Haskell.TH.Syntax
-import qualified Data.Foldable as Foldable
-import qualified Data.Semigroup.Foldable.Class as Foldable1
-import qualified Data.Vector as Vector
-import qualified Data.Vector.Mutable as MVector
-import qualified Data.Vector.NonEmpty as NonEmpty
-import qualified Prelude
-
--- | A circular, immutable vector. This type is equivalent to
---   @'Data.List.cycle' xs@ for some finite, nonempty @xs@, but
---   with /O(1)/ access and /O(1)/ rotations. Indexing
---   into this type is always total.
-data CircularVector a = CircularVector
-  { vector :: {-# UNPACK #-} !(NonEmptyVector a)
-  , rotation :: {-# UNPACK #-} !Int
-  }
-  deriving stock
-    ( Functor -- ^ @since 0.1
-    , Generic -- ^ @since 0.1.1
-    , Ord     -- ^ @since 0.1
-    , Read    -- ^ @since 0.1
-    , Show    -- ^ @since 0.1
-    )
-  deriving anyclass
-    ( NFData -- ^ @since 0.1.1
-    )
-
--- | @since 0.1.1
-instance Traversable CircularVector where
-  traverse :: (Applicative f) => (a -> f b) -> CircularVector a -> f (CircularVector b)
-  traverse f (CircularVector v rot) =
-    CircularVector <$> traverse f v <*> pure rot
-
--- | @since 0.1
-instance Eq a => Eq (CircularVector a) where
-  (==) :: CircularVector a -> CircularVector a -> Bool
-  c0@(CircularVector x rx) == c1@(CircularVector y ry)
-    | NonEmpty.length x /= NonEmpty.length y = False
-    | rx == ry = x == y
-    | otherwise = getAll $ flip Prelude.foldMap [0..NonEmpty.length x-1] $ \i -> All (index c0 i == index c1 i)
-
--- | The 'Semigroup' @('<>')@ operation behaves by un-rolling
---   the two vectors so that their rotation is 0, concatenating
---   them, returning a new vector with a 0-rotation.
---
---   @since 0.1
-instance Semigroup (CircularVector a) where
-  (<>) :: CircularVector a -> CircularVector a -> CircularVector a
-  lhs <> rhs = CircularVector v 0
-    where
-      szLhs = length lhs
-      szRhs = length rhs
-      sz = szLhs + szRhs
-      v = NonEmpty.unsafeFromVector
-            $ Vector.generate sz
-            $ \ix -> if ix < szLhs
-                then index lhs ix
-                else index rhs (ix - szLhs)
-  {-# inline (<>) #-}
-
--- | @since 0.1
-instance Foldable CircularVector where
-  foldMap :: Monoid m => (a -> m) -> CircularVector a -> m
-  foldMap = Data.Vector.Circular.foldMap
-  {-# inline foldMap #-}
-
-#if MIN_VERSION_base(4,13,0)
-  foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m
-  foldMap' = Data.Vector.Circular.foldMap'
-  {-# inline foldMap' #-}
-#endif /* MIN_VERSION_base(4,13,0) */
-
-  null :: CircularVector a -> Bool
-  null _ = False -- nonempty structure is always not null
-  {-# inline null #-}
-
-  length :: CircularVector a -> Int
-  length = Data.Vector.Circular.length
-  {-# inline length #-}
-
--- | @since 0.1
-instance Foldable1 CircularVector where
-  foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m
-  foldMap1 = Data.Vector.Circular.foldMap1
-  {-# inline foldMap1 #-}
-
--- | @since 0.1
-instance Lift a => Lift (CircularVector a) where
-  lift c = do
-    v <- [|NonEmpty.toVector (vector c)|]
-    r <- [|rotation c|]
-    pure $ ConE ''CircularVector
-      `AppE` (VarE 'NonEmpty.unsafeFromVector `AppE` v)
-      `AppE` r
-#if MIN_VERSION_template_haskell(2,16,0)
-  liftTyped = unsafeTExpCoerce . lift
-#endif /* MIN_VERSION_template_haskell(2,16,0) */
-
--- | Get the length of a 'CircularVector'.
---
---   @since 0.1
-length :: CircularVector a -> Int
-length (CircularVector v _) = NonEmpty.length v
-{-# inline length #-}
-
--- | Lazily-accumulating monoidal fold over a 'CircularVector'.
---   @since 0.1
-foldMap :: Monoid m => (a -> m) -> CircularVector a -> m
-foldMap f = \v ->
-  let len = Data.Vector.Circular.length v
-      go !ix
-        | ix < len = f (index v ix) <> go (ix + 1)
-        | otherwise = mempty
-  in go 0
-{-# inline foldMap #-}
-
--- | Strictly-accumulating monoidal fold over a 'CircularVector'.
---
---   @since 0.1
-foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m
-foldMap' f = \v ->
-  let len = Data.Vector.Circular.length v
-      go !ix !acc
-        | ix < len = go (ix + 1) (acc <> f (index v ix))
-        | otherwise = acc
-  in go 0 mempty
-{-# inline foldMap' #-}
-
--- | @since 0.1
-foldr :: (a -> b -> b) -> b -> CircularVector a -> b
-foldr = Foldable.foldr
-
--- | @since 0.1
-foldl :: (b -> a -> b) -> b -> CircularVector a -> b
-foldl = Foldable.foldl
-
--- | @since 0.1
-foldr' :: (a -> b -> b) -> b -> CircularVector a -> b
-foldr' = Foldable.foldr'
-
--- | @since 0.1
-foldl' :: (b -> a -> b) -> b -> CircularVector a -> b
-foldl' = Foldable.foldl'
-
--- | @since 0.1
-foldr1 :: (a -> a -> a) -> CircularVector a -> a
-foldr1 = Foldable.foldr1
-
--- | @since 0.1
-foldl1 :: (a -> a -> a) -> CircularVector a -> a
-foldl1 = Foldable.foldl1
-
--- | @since 0.1
-toNonEmpty :: CircularVector a -> NonEmpty a
-toNonEmpty = Foldable1.toNonEmpty
-
--- | Lazily-accumulating semigroupoidal fold over
---   a 'CircularVector'.
---
---   @since 0.1
-foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m
-foldMap1 f = \v ->
-  let len = Data.Vector.Circular.length v
-      go !ix
-        | ix < len-1 = f (index v ix) <> go (ix + 1)
-        | otherwise  = f (last v)
-  in go 0
-{-# inline foldMap1 #-}
-
--- | Strictly-accumulating semigroupoidal fold over
---   a 'CircularVector'.
---
---   @since 0.1
-foldMap1' :: Semigroup m => (a -> m) -> CircularVector a -> m
-foldMap1' f = \v ->
-  let len = Data.Vector.Circular.length v
-      go !ix !acc
-        | ix < len = go (ix + 1) (acc <> f (index v ix))
-        | otherwise = acc
-  in go 1 (f (head v))
-{-# inline foldMap1' #-}
-
--- | Construct a 'Vector' from a 'CircularVector'.
---
---   @since 0.1
-toVector :: CircularVector a -> Vector a
-toVector v = Vector.generate (length v) (index v)
-
--- | Construct a 'NonEmptyVector' from a 'CircularVector'.
---
---   @since 0.1.1
-toNonEmptyVector :: CircularVector a -> NonEmptyVector a
-toNonEmptyVector v = NonEmpty.generate1 (length v) (index v)
-
--- | Construct a 'CircularVector' from a 'NonEmptyVector'.
---
---   @since 0.1
-fromVector :: NonEmptyVector a -> CircularVector a
-fromVector v = CircularVector v 0
-{-# inline fromVector #-}
-
--- | Construct a 'CircularVector' from a 'Vector'.
---
---   Calls @'error'@ if the input vector is empty.
---
---   @since 0.1
-unsafeFromVector :: Vector a -> CircularVector a
-unsafeFromVector = fromVector . NonEmpty.unsafeFromVector
-
--- | Construct a 'CircularVector' from a list.
---
---   @since 0.1
-fromList :: [a] -> Maybe (CircularVector a)
-fromList xs = fromListN (Prelude.length xs) xs
-{-# inline fromList #-}
-
--- | Construct a 'CircularVector' from a list with a size hint.
---
---   @since 0.1
-fromListN :: Int -> [a] -> Maybe (CircularVector a)
-fromListN n xs = fromVector <$> (NonEmpty.fromListN n xs)
-{-# inline fromListN #-}
-
--- | Construct a 'CircularVector' from a list.
---
---   Calls @'error'@ if the input list is empty.
---
---   @since 0.1
-unsafeFromList :: [a] -> CircularVector a
-unsafeFromList xs = unsafeFromListN (Prelude.length xs) xs
-
--- | Construct a 'CircularVector' from a list with a size hint.
---
---   Calls @'error'@ if the input list is empty, or
---   if the size hint is @'<=' 0@.
---
---    @since 0.1
-unsafeFromListN :: Int -> [a] -> CircularVector a
-unsafeFromListN n xs
-  | n <= 0 = error "Data.Vector.Circular.unsafeFromListN: invalid length!"
-  | otherwise = unsafeFromVector (Vector.fromListN n xs)
-
--- | Construct a singleton 'CircularVector.
---
---   @since 0.1
-singleton :: a -> CircularVector a
-singleton = fromVector . NonEmpty.singleton
-{-# inline singleton #-}
-
--- | Index into a 'CircularVector'. This is always total.
---
---   @since 0.1
-index :: CircularVector a -> Int -> a
-index (CircularVector v r) = \ !ix ->
-  let len = NonEmpty.length v
-  in NonEmpty.unsafeIndex v (unsafeMod (ix + r) len)
-{-# inline index #-}
-
--- | Get the first element of a 'CircularVector'. This is always total.
---
---   @since 0.1
-head :: CircularVector a -> a
-head v = index v 0
-{-# inline head #-}
-
--- | Get the last element of a 'CircularVector'. This is always total.
---
---   @since 0.1
-last :: CircularVector a -> a
-last v = index v (Data.Vector.Circular.length v - 1)
-{-# inline last #-}
-
--- | Rotate the vector to left by @n@ number of elements.
---
---   /Note/: Right rotations start to break down due to
---   arithmetic overflow when the size of the input vector is
---   @'>' 'maxBound' @'Int'@
---
---   @since 0.1
-rotateRight :: Int -> CircularVector a -> CircularVector a
-rotateRight r' (CircularVector v r) = CircularVector v h
-  where
-    len = NonEmpty.length v
-    h = unsafeMod (r + unsafeMod r' len) len
-{-# inline rotateRight #-}
-
--- | Rotate the vector to the left by @n@ number of elements.
---
---   /Note/: Left rotations start to break down due to
---   arithmetic underflow when the size of the input vector is
---   @'>' 'maxBound' @'Int'@
---
---   @since 0.1
-rotateLeft :: Int -> CircularVector a -> CircularVector a
-rotateLeft r' (CircularVector v r) = CircularVector v h
-  where
-    len = NonEmpty.length v
-    h = unsafeMod (r - unsafeMod r' len) len
-{-# inline rotateLeft #-}
-
--- | Construct a 'CircularVector' at compile-time using
---   typed Template Haskell.
---
---   @since 0.1
-vec :: Lift a => [a] -> Q (TExp (CircularVector a))
-vec [] = fail "Cannot create an empty CircularVector!"
-vec xs =
-#if MIN_VERSION_template_haskell(2,16,0)
-  liftTyped (unsafeFromList xs)
-#else
-  unsafeTExpCoerce [|unsafeFromList xs|]
-#endif /* MIN_VERSION_template_haskell(2,16,0) */
-
--- | @since 0.1
-equivalent :: Ord a => CircularVector a -> CircularVector a -> Bool
-equivalent x y = vector (canonise x) == vector (canonise y)
-
--- | @since 0.1
-canonise :: Ord a => CircularVector a -> CircularVector a
-canonise (CircularVector v r) = CircularVector v' (r - lr)
-  where
-    lr = leastRotation (NonEmpty.toVector v)
-    v' = toNonEmptyVector (rotateRight lr (CircularVector v 0))
-
--- | @since 0.1
-leastRotation :: forall a. (Ord a) => Vector a -> Int
-leastRotation v = runST go
-  where
-    go :: forall s. ST s Int
-    go = do
-      let s = v <> v
-      let len = Vector.length s
-      f <- MVector.replicate @_ @Int len (-1)
-      kVar <- newMutVar @_ @Int 0
-      forM_ [1..len-1] $ \j -> do
-        sj <- Vector.indexM s j
-        i0 <- readMutVar kVar >>= \k -> MVector.read f (j - k - 1)
-        let loop i = do
-              a <- readMutVar kVar >>= \k -> Vector.indexM s (k + i + 1)
-              if (i /= (-1) && sj /= a)
-                then do
-                  when (sj < a) (writeMutVar kVar (j - i - 1))
-                  loop =<< MVector.read f i
-                else pure i
-        i <- loop i0
-        a <- readMutVar kVar >>= \k -> Vector.indexM s (k + i + 1)
-        if sj /= a
-          then do
-            readMutVar kVar >>= \k -> when (sj < (s Vector.! k)) (writeMutVar kVar j)
-            readMutVar kVar >>= \k -> MVector.write f (j - k) (-1)
-          else do
-            readMutVar kVar >>= \k -> MVector.write f (j - k) (i + 1)
-      readMutVar kVar
-
--- only safe if second argument is nonzero.
--- used internally for modulus operations with length.
-unsafeMod :: Int -> Int -> Int
-unsafeMod = GHC.Base.modInt
-{-# inline unsafeMod #-}
-
--- | /O(min(m,n))/ Zip two circular vectors with the given function.
---
---   @since 0.1.1
-zipWith :: (a -> b -> c) -> CircularVector a -> CircularVector b -> CircularVector c
-zipWith f a b = fromVector $ NonEmpty.zipWith f (toNonEmptyVector a) (toNonEmptyVector b)
-
--- | Zip three circular vectors with the given function.
---
---   @since 0.1.1
-zipWith3 :: (a -> b -> c -> d) -> CircularVector a -> CircularVector b -> CircularVector c
-  -> CircularVector d
-zipWith3 f a b c = fromVector $
-  NonEmpty.zipWith3 f (toNonEmptyVector a) (toNonEmptyVector b) (toNonEmptyVector c)
-
--- | /O(min(n,m))/ Elementwise pairing of circular vector elements.
---   This is a special case of 'zipWith' where the function argument is '(,)'
---
---   @since 0.1.1
-zip :: CircularVector a -> CircularVector b -> CircularVector (a,b)
-zip a b = fromVector $ NonEmpty.zip (toNonEmptyVector a) (toNonEmptyVector b)
-
--- | Zip together three circular vectors.
---
---   @since 0.1.1
-zip3 :: CircularVector a -> CircularVector b -> CircularVector c -> CircularVector (a,b,c)
-zip3 a b c = fromVector $ NonEmpty.zip3 (toNonEmptyVector a) (toNonEmptyVector b) (toNonEmptyVector c)
-
--- | /O(n)/ Reverse a circular vector.
---
---   @since 0.1.1
-reverse :: CircularVector a -> CircularVector a
-reverse = fromVector . NonEmpty.reverse . toNonEmptyVector
-
--- | /O(n)/ Rotate to the minimum element of the circular vector according to the
---   given comparison function.
---
---   @since 0.1.1
-rotateToMinimumBy :: (a -> a -> Ordering) -> CircularVector a -> CircularVector a
-rotateToMinimumBy f (CircularVector v _rot) =
-  CircularVector v (NonEmpty.minIndexBy f v)
-
--- | /O(n)/ Rotate to the maximum element of the circular vector according to the
---   given comparison function.
---
---   @since 0.1.1
-rotateToMaximumBy :: (a -> a -> Ordering) -> CircularVector a -> CircularVector a
-rotateToMaximumBy f (CircularVector v _rot) =
-  CircularVector v (NonEmpty.maxIndexBy f v)
-
--- | /O(n)/ Check if all elements satisfy the predicate.
---
---   @since 0.1.1
-all :: (a -> Bool) -> CircularVector a -> Bool
-all f = NonEmpty.all f . vector
-
--- | /O(n)/ Check if any element satisfies the predicate.
---
---   @since 0.1.1
-any :: (a -> Bool) -> CircularVector a -> Bool
-any f = NonEmpty.any f . vector
-
--- | /O(n)/ Check if all elements are True.
---
---   @since 0.1.1
-and :: CircularVector Bool -> Bool
-and = NonEmpty.and . vector
-
--- | /O(n)/ Check if any element is True.
---
---   @since 0.1.1
-or :: CircularVector Bool -> Bool
-or = NonEmpty.or . vector
-
--- | /O(n)/ Compute the sum of the elements.
---
---   @since 0.1.1
-sum :: Num a => CircularVector a -> a
-sum = NonEmpty.sum . vector
-
--- | /O(n)/ Compute the product of the elements.
---
---   @since 0.1.1
-product :: Num a => CircularVector a -> a
-product = NonEmpty.sum . vector
-
--- | /O(n)/ Yield the maximum element of the circular vector.
---
---   @since 0.1.1
-maximum :: Ord a => CircularVector a -> a
-maximum = NonEmpty.maximum . vector
-
--- | /O(n)/ Yield the maximum element of a circular vector according to the
---   given comparison function.
---
---   @since 0.1.1
-maximumBy :: (a -> a -> Ordering) -> CircularVector a -> a
-maximumBy f = NonEmpty.maximumBy f . vector
-
--- | /O(n)/ Yield the minimum element of the circular vector.
---
---   @since 0.1.1
-minimum :: Ord a => CircularVector a -> a
-minimum = NonEmpty.minimum . vector
-
--- | /O(n)/ Yield the minimum element of a circular vector according to the
---   given comparison function.
---
---   @since 0.1.1
-minimumBy :: (a -> a -> Ordering) -> CircularVector a -> a
-minimumBy f = NonEmpty.minimumBy f . vector
+  , RankNTypes
+#-}
+
+module Data.Vector.Circular
+  ( -- * Types
+    CircularVector(..)
+
+    -- * Construction
+    -- ** Initialization
+  , singleton
+  , replicate
+  , replicate1
+  , generate
+  , generate1
+  , iterateN
+  , iterateN1
+    -- ** Monad Initialization
+  , replicateM
+  , replicate1M
+  , generateM
+  , generate1M
+  , iterateNM
+  , iterateN1M
+  , create
+  , unsafeCreate
+  , createT
+  , unsafeCreateT
+    -- ** Unfolding
+  , unfoldr
+  , unfoldr1
+  , unfoldrN
+  , unfoldr1N
+  , unfoldrM
+  , unfoldr1M
+  , unfoldrNM
+  , unfoldr1NM
+  , constructN
+  , constructrN
+    -- ** Enumeration
+  , enumFromN
+  , enumFromN1
+  , enumFromStepN
+  , enumFromStepN1
+  , enumFromTo
+  , enumFromThenTo
+    -- ** Concatenation
+  , cons
+  , consV
+  , snoc
+  , snocV
+  , (Data.Vector.Circular.++)
+  , concat
+  , concat1
+    -- ** Restricting memory usage
+  , force
+
+    -- ** Template Haskell
+  , vec
+
+    -- * Conversion
+  , toVector
+  , fromVector
+  , fromVector'
+  , unsafeFromVector
+  , toNonEmptyVector
+  , toList
+  , fromList
+  , fromListN
+  , unsafeFromList
+  , unsafeFromListN
+
+    -- * Rotation
+  , rotateLeft
+  , rotateRight
+
+    -- * Comparisons
+  , equivalent
+  , canonise
+  , leastRotation
+
+    -- * Folds
+  , foldMap
+  , foldMap'
+  , foldr
+  , foldl
+  , foldr'
+  , foldl'
+  , foldr1
+  , foldl1
+  , foldMap1
+  , foldMap1'
+  , toNonEmpty
+
+    -- * Specialized folds
+  , all
+  , any
+  , and
+  , or
+  , sum
+  , product
+  , maximum
+  , maximumBy
+  , minimum
+  , minimumBy
+  , rotateToMinimumBy
+  , rotateToMaximumBy
+
+    -- * Elementwise operations
+    -- ** Indexing
+  , index
+  , head
+  , last
+
+    -- ** Mapping
+  , map
+  , imap
+  , concatMap
+
+    -- ** Monadic mapping
+  , mapM
+  , imapM
+  , mapM_
+  , imapM_
+  , forM
+  , forM_
+
+    -- ** Zipping
+  , zipWith
+  , zipWith3
+  , zip
+  , zip3
+
+    -- ** Unzipping
+  , unzip
+  , unzip3
+
+    -- ** Filtering
+  , uniq
+  , mapMaybe
+  , imapMaybe
+  , filter
+  , ifilter
+  , filterM
+  , ifilterM
+  , takeWhile
+  , dropWhile
+
+    -- * Partitioning
+  , partition
+  , unstablePartition
+  , span
+  , break
+
+    -- * Searching
+  , elem
+  , notElem
+  , find
+  , findIndex
+  , findIndices
+  , elemIndex
+  , elemIndices
+
+    -- * Permutations
+  , reverse
+  , backpermute
+  , unsafeBackpermute
+
+    -- * Safe destructive updates
+  , modify
+
+    -- * Monadic Sequencing
+  , sequence
+  , sequence_
+  ) where
+
+import qualified Control.Monad (when, forM_)
+import Control.Monad.ST (ST, runST)
+import Control.DeepSeq
+#if MIN_VERSION_base(4,13,0)
+-- import Data.Foldable (foldMap')
+#endif /* MIN_VERSION_base(4,13,0) */
+import Data.List.NonEmpty (NonEmpty((:|)))
+import Data.Primitive.MutVar ( newMutVar, readMutVar, writeMutVar )
+import Data.Semigroup.Foldable.Class (Foldable1)
+import Data.Monoid (All(..))
+import Data.Vector (Vector)
+import Data.Vector.NonEmpty (NonEmptyVector)
+import Data.Functor.Classes
+import Text.Read (readPrec)
+import GHC.Base (modInt)
+import GHC.Generics (Generic)
+import Prelude hiding (head, length, last, map, concat, takeWhile
+                      ,dropWhile, span, break, elem, notElem, reverse
+                      ,mapM, mapM_, foldMap, foldr
+                      ,foldl, foldr1, foldl1, all, any, and, or, sum
+                      ,product, maximum, minimum, concatMap
+                      ,zipWith, zipWith3, zip, zip3, replicate, enumFromTo
+                      ,enumFromThenTo, (++))
+import Language.Haskell.TH.Syntax
+import qualified Data.Foldable as Foldable
+import qualified Data.Semigroup.Foldable.Class as Foldable1
+import qualified Data.Vector as Vector
+import qualified Data.Vector.Mutable as MVector
+import qualified Data.Vector.NonEmpty as NonEmpty
+import qualified Prelude
+
+
+-- | A circular, immutable vector. This type is equivalent to
+--   @'Data.List.cycle' xs@ for some finite, nonempty @xs@, but
+--   with /O(1)/ access and /O(1)/ rotations. Indexing
+--   into this type is always total.
+data CircularVector a = CircularVector
+  { vector :: {-# UNPACK #-} !(NonEmptyVector a)
+  , rotation :: {-# UNPACK #-} !Int
+  }
+  deriving stock
+    ( Functor -- ^ @since 0.1
+    , Generic -- ^ @since 0.1.1
+    , Ord     -- ^ @since 0.1
+    , Read    -- ^ @since 0.1
+    , Show    -- ^ @since 0.1
+    )
+  deriving anyclass
+    ( NFData -- ^ @since 0.1.1
+    )
+
+-- | @since 0.1.1
+instance Traversable CircularVector where
+  traverse :: (Applicative f) => (a -> f b) -> CircularVector a -> f (CircularVector b)
+  traverse f (CircularVector v rot) =
+    CircularVector <$> traverse f v <*> pure rot
+
+-- | @since 0.1
+instance Eq a => Eq (CircularVector a) where
+  (==) :: CircularVector a -> CircularVector a -> Bool
+  (==) = liftEq (==)
+
+-- | @since 0.1.2
+instance Eq1 CircularVector where
+  liftEq :: (a -> b -> Bool) -> CircularVector a -> CircularVector b -> Bool
+  liftEq eq c0@(CircularVector x rx) c1@(CircularVector y ry)
+    | NonEmpty.length x /= NonEmpty.length y = False
+    | rx == ry = liftEq eq x y
+    | otherwise = getAll $ flip Prelude.foldMap [0..NonEmpty.length x-1] $ \i ->
+        All (index c0 i `eq` index c1 i)
+
+-- | @since 0.1.2
+instance Ord1 CircularVector where
+  liftCompare :: (a -> b -> Ordering) -> CircularVector a -> CircularVector b -> Ordering
+  liftCompare cmp (CircularVector x rx) (CircularVector y ry)
+    = liftCompare cmp x y <> compare rx ry
+
+-- | @since 0.1.2
+instance Show1 CircularVector where
+  liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> CircularVector a -> ShowS
+  liftShowsPrec sp sl d (CircularVector x rx) =
+    showsBinaryWith (liftShowsPrec sp sl) showsPrec "CircularVector" d x rx
+
+-- | @since 0.1.2
+instance Read1 CircularVector where
+  liftReadPrec rp rl = readData $
+    readBinaryWith (liftReadPrec rp rl) readPrec "CircularVector" CircularVector
+  liftReadListPrec = liftReadListPrecDefault
+
+-- | The 'Semigroup' @('<>')@ operation behaves by un-rolling
+--   the two vectors so that their rotation is 0, concatenating
+--   them, returning a new vector with a 0-rotation.
+--
+--   @since 0.1
+instance Semigroup (CircularVector a) where
+  (<>) :: CircularVector a -> CircularVector a -> CircularVector a
+  lhs <> rhs = CircularVector v 0
+    where
+      szLhs = length lhs
+      szRhs = length rhs
+      sz = szLhs + szRhs
+      v = NonEmpty.unsafeFromVector
+            $ Vector.generate sz
+            $ \ix -> if ix < szLhs
+                then index lhs ix
+                else index rhs (ix - szLhs)
+  {-# inline (<>) #-}
+
+-- | @since 0.1
+instance Foldable CircularVector where
+  foldMap :: Monoid m => (a -> m) -> CircularVector a -> m
+  foldMap = Data.Vector.Circular.foldMap
+  {-# inline foldMap #-}
+
+#if MIN_VERSION_base(4,13,0)
+  foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m
+  foldMap' = Data.Vector.Circular.foldMap'
+  {-# inline foldMap' #-}
+#endif /* MIN_VERSION_base(4,13,0) */
+
+  null :: CircularVector a -> Bool
+  null _ = False -- nonempty structure is always not null
+  {-# inline null #-}
+
+  length :: CircularVector a -> Int
+  length = Data.Vector.Circular.length
+  {-# inline length #-}
+
+-- | @since 0.1
+instance Foldable1 CircularVector where
+  foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m
+  foldMap1 = Data.Vector.Circular.foldMap1
+  {-# inline foldMap1 #-}
+
+-- | @since 0.1
+instance Lift a => Lift (CircularVector a) where
+  lift c = do
+    v <- [|NonEmpty.toVector (vector c)|]
+    r <- [|rotation c|]
+    pure $ ConE ''CircularVector
+      `AppE` (VarE 'NonEmpty.unsafeFromVector `AppE` v)
+      `AppE` r
+#if MIN_VERSION_template_haskell(2,16,0)
+  liftTyped = unsafeTExpCoerce . lift
+#endif /* MIN_VERSION_template_haskell(2,16,0) */
+
+-- | Get the length of a 'CircularVector'.
+--
+--   @since 0.1
+length :: CircularVector a -> Int
+length (CircularVector v _) = NonEmpty.length v
+{-# inline length #-}
+
+-- | Lazily-accumulating monoidal fold over a 'CircularVector'.
+--   @since 0.1
+foldMap :: Monoid m => (a -> m) -> CircularVector a -> m
+foldMap f = \v ->
+  let len = Data.Vector.Circular.length v
+      go !ix
+        | ix < len = f (index v ix) <> go (ix + 1)
+        | otherwise = mempty
+  in go 0
+{-# inline foldMap #-}
+
+-- | Strictly-accumulating monoidal fold over a 'CircularVector'.
+--
+--   @since 0.1
+foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m
+foldMap' f = \v ->
+  let len = Data.Vector.Circular.length v
+      go !ix !acc
+        | ix < len = go (ix + 1) (acc <> f (index v ix))
+        | otherwise = acc
+  in go 0 mempty
+{-# inline foldMap' #-}
+
+-- | @since 0.1
+foldr :: (a -> b -> b) -> b -> CircularVector a -> b
+foldr = Foldable.foldr
+
+-- | @since 0.1
+foldl :: (b -> a -> b) -> b -> CircularVector a -> b
+foldl = Foldable.foldl
+
+-- | @since 0.1
+foldr' :: (a -> b -> b) -> b -> CircularVector a -> b
+foldr' = Foldable.foldr'
+
+-- | @since 0.1
+foldl' :: (b -> a -> b) -> b -> CircularVector a -> b
+foldl' = Foldable.foldl'
+
+-- | @since 0.1
+foldr1 :: (a -> a -> a) -> CircularVector a -> a
+foldr1 = Foldable.foldr1
+
+-- | @since 0.1
+foldl1 :: (a -> a -> a) -> CircularVector a -> a
+foldl1 = Foldable.foldl1
+
+-- | @since 0.1
+toNonEmpty :: CircularVector a -> NonEmpty a
+toNonEmpty = Foldable1.toNonEmpty
+
+-- | Lazily-accumulating semigroupoidal fold over
+--   a 'CircularVector'.
+--
+--   @since 0.1
+foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m
+foldMap1 f = \v ->
+  let len = Data.Vector.Circular.length v
+      go !ix
+        | ix < len-1 = f (index v ix) <> go (ix + 1)
+        | otherwise  = f (last v)
+  in go 0
+{-# inline foldMap1 #-}
+
+-- | Strictly-accumulating semigroupoidal fold over
+--   a 'CircularVector'.
+--
+--   @since 0.1
+foldMap1' :: Semigroup m => (a -> m) -> CircularVector a -> m
+foldMap1' f = \v ->
+  let len = Data.Vector.Circular.length v
+      go !ix !acc
+        | ix < len = go (ix + 1) (acc <> f (index v ix))
+        | otherwise = acc
+  in go 1 (f (head v))
+{-# inline foldMap1' #-}
+
+-- | /O(n)/ Construct a 'Vector' from a 'CircularVector'.
+--
+--   @since 0.1
+toVector :: CircularVector a -> Vector a
+toVector v = Vector.generate (length v) (index v)
+
+-- | /O(n)/ Construct a 'NonEmptyVector' from a 'CircularVector'.
+--
+--   @since 0.1.1
+toNonEmptyVector :: CircularVector a -> NonEmptyVector a
+toNonEmptyVector v = NonEmpty.generate1 (length v) (index v)
+
+-- | /O(1)/ Construct a 'CircularVector' from a 'NonEmptyVector'.
+--
+--   @since 0.1
+fromVector :: NonEmptyVector a -> CircularVector a
+fromVector v = CircularVector v 0
+{-# inline fromVector #-}
+
+-- | /O(1)/ Construct a 'CircularVector' from a 'NonEmptyVector'.
+--
+--   @since 0.1.2
+fromVector' :: Vector a -> Maybe (CircularVector a)
+fromVector' v = CircularVector <$> NonEmpty.fromVector v <*> pure 0
+{-# inline fromVector' #-}
+
+-- | /O(1)/ Construct a 'CircularVector' from a 'Vector'.
+--
+--   Calls @'error'@ if the input vector is empty.
+--
+--   @since 0.1
+unsafeFromVector :: Vector a -> CircularVector a
+unsafeFromVector = fromVector . NonEmpty.unsafeFromVector
+
+-- | /O(n)/ Convert from a circular vector to a list.
+--
+--
+-- >>> let nev = unsafeFromList [1..3] in toList nev
+-- [1,2,3]
+--
+--   @since 0.1.2
+toList :: CircularVector a -> [a]
+toList = Vector.toList . toVector
+
+-- | /O(n)/ Construct a 'CircularVector' from a list.
+--
+--   @since 0.1
+fromList :: [a] -> Maybe (CircularVector a)
+fromList xs = fromListN (Prelude.length xs) xs
+{-# inline fromList #-}
+
+-- | Construct a 'CircularVector' from a list with a size hint.
+--
+--   @since 0.1
+fromListN :: Int -> [a] -> Maybe (CircularVector a)
+fromListN n xs = fromVector <$> (NonEmpty.fromListN n xs)
+{-# inline fromListN #-}
+
+-- | /O(n)/ Construct a 'CircularVector' from a list.
+--
+--   Calls @'error'@ if the input list is empty.
+--
+--   @since 0.1
+unsafeFromList :: [a] -> CircularVector a
+unsafeFromList xs = unsafeFromListN (Prelude.length xs) xs
+
+-- | /O(n)/ Construct a 'CircularVector' from a list with a size hint.
+--
+--   Calls @'error'@ if the input list is empty, or
+--   if the size hint is @'<=' 0@.
+--
+--    @since 0.1
+unsafeFromListN :: Int -> [a] -> CircularVector a
+unsafeFromListN n xs
+  | n <= 0 = error "Data.Vector.Circular.unsafeFromListN: invalid length!"
+  | otherwise = unsafeFromVector (Vector.fromListN n xs)
+
+-- | /O(1)/ Construct a singleton 'CircularVector.
+--
+--   @since 0.1
+singleton :: a -> CircularVector a
+singleton = fromVector . NonEmpty.singleton
+{-# inline singleton #-}
+
+-- | /O(1)/ Index into a 'CircularVector'. This is always total.
+--
+--   @since 0.1
+index :: CircularVector a -> Int -> a
+index (CircularVector v r) = \ !ix ->
+  let len = NonEmpty.length v
+  in NonEmpty.unsafeIndex v (unsafeMod (ix + r) len)
+{-# inline index #-}
+
+-- | /O(1)/ Get the first element of a 'CircularVector'. This is always total.
+--
+--   @since 0.1
+head :: CircularVector a -> a
+head v = index v 0
+{-# inline head #-}
+
+-- | /O(1)/ Get the last element of a 'CircularVector'. This is always total.
+--
+--   @since 0.1
+last :: CircularVector a -> a
+last v = index v (Data.Vector.Circular.length v - 1)
+{-# inline last #-}
+
+-- | /O(1)/ Rotate the vector to left by @n@ number of elements.
+--
+--   /Note/: Right rotations start to break down due to
+--   arithmetic overflow when the size of the input vector is
+--   @'>' 'maxBound' @'Int'@
+--
+--   @since 0.1
+rotateRight :: Int -> CircularVector a -> CircularVector a
+rotateRight r' (CircularVector v r) = CircularVector v h
+  where
+    len = NonEmpty.length v
+    h = unsafeMod (r + unsafeMod r' len) len
+{-# inline rotateRight #-}
+
+-- | /O(1)/ Rotate the vector to the left by @n@ number of elements.
+--
+--   /Note/: Left rotations start to break down due to
+--   arithmetic underflow when the size of the input vector is
+--   @'>' 'maxBound' @'Int'@
+--
+--   @since 0.1
+rotateLeft :: Int -> CircularVector a -> CircularVector a
+rotateLeft r' (CircularVector v r) = CircularVector v h
+  where
+    len = NonEmpty.length v
+    h = unsafeMod (r - unsafeMod r' len) len
+{-# inline rotateLeft #-}
+
+-- | Construct a 'CircularVector' at compile-time using
+--   typed Template Haskell.
+--
+--   @since 0.1
+vec :: Lift a => [a] -> Q (TExp (CircularVector a))
+vec [] = fail "Cannot create an empty CircularVector!"
+vec xs =
+#if MIN_VERSION_template_haskell(2,16,0)
+  liftTyped (unsafeFromList xs)
+#else
+  unsafeTExpCoerce [|unsafeFromList xs|]
+#endif /* MIN_VERSION_template_haskell(2,16,0) */
+
+-- | @since 0.1
+equivalent :: Ord a => CircularVector a -> CircularVector a -> Bool
+equivalent x y = vector (canonise x) == vector (canonise y)
+
+-- | @since 0.1
+canonise :: Ord a => CircularVector a -> CircularVector a
+canonise (CircularVector v r) = CircularVector v' (r - lr)
+  where
+    lr = leastRotation (NonEmpty.toVector v)
+    v' = toNonEmptyVector (rotateRight lr (CircularVector v 0))
+
+-- | @since 0.1
+leastRotation :: forall a. (Ord a) => Vector a -> Int
+leastRotation v = runST go
+  where
+    go :: forall s. ST s Int
+    go = do
+      let s = v <> v
+      let len = Vector.length s
+      f <- MVector.replicate @_ @Int len (-1)
+      kVar <- newMutVar @_ @Int 0
+      Control.Monad.forM_ [1..len-1] $ \j -> do
+        sj <- Vector.indexM s j
+        i0 <- readMutVar kVar >>= \k -> MVector.read f (j - k - 1)
+        let loop i = do
+              a <- readMutVar kVar >>= \k -> Vector.indexM s (k + i + 1)
+              if (i /= (-1) && sj /= a)
+                then do
+                  Control.Monad.when (sj < a) (writeMutVar kVar (j - i - 1))
+                  loop =<< MVector.read f i
+                else pure i
+        i <- loop i0
+        a <- readMutVar kVar >>= \k -> Vector.indexM s (k + i + 1)
+        if sj /= a
+          then do
+            readMutVar kVar >>= \k -> Control.Monad.when (sj < (s Vector.! k)) (writeMutVar kVar j)
+            readMutVar kVar >>= \k -> MVector.write f (j - k) (-1)
+          else do
+            readMutVar kVar >>= \k -> MVector.write f (j - k) (i + 1)
+      readMutVar kVar
+
+-- only safe if second argument is nonzero.
+-- used internally for modulus operations with length.
+unsafeMod :: Int -> Int -> Int
+unsafeMod = GHC.Base.modInt
+{-# inline unsafeMod #-}
+
+-- | /O(min(m,n))/ Zip two circular vectors with the given function.
+--
+--   @since 0.1.1
+zipWith :: (a -> b -> c) -> CircularVector a -> CircularVector b -> CircularVector c
+zipWith f a b = fromVector $ NonEmpty.zipWith f (toNonEmptyVector a) (toNonEmptyVector b)
+
+-- | Zip three circular vectors with the given function.
+--
+--   @since 0.1.1
+zipWith3 :: (a -> b -> c -> d) -> CircularVector a -> CircularVector b -> CircularVector c
+  -> CircularVector d
+zipWith3 f a b c = fromVector $
+  NonEmpty.zipWith3 f (toNonEmptyVector a) (toNonEmptyVector b) (toNonEmptyVector c)
+
+-- | /O(min(n,m))/ Elementwise pairing of circular vector elements.
+--   This is a special case of 'zipWith' where the function argument is '(,)'
+--
+--   @since 0.1.1
+zip :: CircularVector a -> CircularVector b -> CircularVector (a,b)
+zip a b = fromVector $ NonEmpty.zip (toNonEmptyVector a) (toNonEmptyVector b)
+
+-- | Zip together three circular vectors.
+--
+--   @since 0.1.1
+zip3 :: CircularVector a -> CircularVector b -> CircularVector c -> CircularVector (a,b,c)
+zip3 a b c = fromVector $ NonEmpty.zip3 (toNonEmptyVector a) (toNonEmptyVector b) (toNonEmptyVector c)
+
+-- | /O(n)/ Reverse a circular vector.
+--
+--   @since 0.1.1
+reverse :: CircularVector a -> CircularVector a
+reverse = fromVector . NonEmpty.reverse . toNonEmptyVector
+
+-- | /O(n)/ Rotate to the minimum element of the circular vector according to the
+--   given comparison function.
+--
+--   @since 0.1.1
+rotateToMinimumBy :: (a -> a -> Ordering) -> CircularVector a -> CircularVector a
+rotateToMinimumBy f (CircularVector v _rot) =
+  CircularVector v (NonEmpty.minIndexBy f v)
+
+-- | /O(n)/ Rotate to the maximum element of the circular vector according to the
+--   given comparison function.
+--
+--   @since 0.1.1
+rotateToMaximumBy :: (a -> a -> Ordering) -> CircularVector a -> CircularVector a
+rotateToMaximumBy f (CircularVector v _rot) =
+  CircularVector v (NonEmpty.maxIndexBy f v)
+
+-- | /O(n)/ Check if all elements satisfy the predicate.
+--
+--   @since 0.1.1
+all :: (a -> Bool) -> CircularVector a -> Bool
+all f = NonEmpty.all f . vector
+
+-- | /O(n)/ Check if any element satisfies the predicate.
+--
+--   @since 0.1.1
+any :: (a -> Bool) -> CircularVector a -> Bool
+any f = NonEmpty.any f . vector
+
+-- | /O(n)/ Check if all elements are True.
+--
+--   @since 0.1.1
+and :: CircularVector Bool -> Bool
+and = NonEmpty.and . vector
+
+-- | /O(n)/ Check if any element is True.
+--
+--   @since 0.1.1
+or :: CircularVector Bool -> Bool
+or = NonEmpty.or . vector
+
+-- | /O(n)/ Compute the sum of the elements.
+--
+--   @since 0.1.1
+sum :: Num a => CircularVector a -> a
+sum = NonEmpty.sum . vector
+
+-- | /O(n)/ Compute the product of the elements.
+--
+--   @since 0.1.1
+product :: Num a => CircularVector a -> a
+product = NonEmpty.sum . vector
+
+-- | /O(n)/ Yield the maximum element of the circular vector.
+--
+--   @since 0.1.1
+maximum :: Ord a => CircularVector a -> a
+maximum = NonEmpty.maximum . vector
+
+-- | /O(n)/ Yield the maximum element of a circular vector according to the
+--   given comparison function.
+--
+--   @since 0.1.1
+maximumBy :: (a -> a -> Ordering) -> CircularVector a -> a
+maximumBy f = NonEmpty.maximumBy f . vector
+
+-- | /O(n)/ Yield the minimum element of the circular vector.
+--
+--   @since 0.1.1
+minimum :: Ord a => CircularVector a -> a
+minimum = NonEmpty.minimum . vector
+
+-- | /O(n)/ Yield the minimum element of a circular vector according to the
+--   given comparison function.
+--
+--   @since 0.1.1
+minimumBy :: (a -> a -> Ordering) -> CircularVector a -> a
+minimumBy f = NonEmpty.minimumBy f . vector
+
+-- | /O(n)/ Circular vector of the given length with the same value in
+-- each position.
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> replicate 3 "a"
+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})
+--
+-- >>> replicate 0 "a"
+-- Nothing
+--
+replicate :: Int -> a -> Maybe (CircularVector a)
+replicate n a = fromVector' (Vector.replicate n a)
+
+-- | /O(n)/ Circular vector of the given length with the same value in
+-- each position.
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> replicate1 3 "a"
+-- CircularVector {vector = ["a","a","a"], rotation = 0}
+--
+-- >>> replicate1 0 "a"
+-- CircularVector {vector = ["a"], rotation = 0}
+--
+-- >>> replicate1 (-1) "a"
+-- CircularVector {vector = ["a"], rotation = 0}
+replicate1 :: Int -> a -> CircularVector a
+replicate1 n a = unsafeFromVector (Vector.replicate (max n 1) a)
+
+-- | /O(n)/ Construct a circular vector of the given length by applying the function to
+-- each index.
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> let f 0 = "a"; f _ = "k"; f :: Int -> String
+--
+-- >>> generate 1 f
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+-- >>> generate 0 f
+-- Nothing
+--
+-- >>> generate 2 f
+-- Just (CircularVector {vector = ["a","k"], rotation = 0})
+--
+generate :: Int -> (Int -> a) -> Maybe (CircularVector a)
+generate n f = fromVector' (Vector.generate n f)
+
+-- | /O(n)/ Construct a circular vector of the given length by applying the function to
+-- each index.
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> let f 0 = "a"; f _ = "k"; f :: Int -> String
+--
+-- >>> toList $ generate1 2 f
+-- ["a","k"]
+--
+-- >>> toList $ generate1 0 f
+-- ["a"]
+--
+-- >>> toList $ generate1 (-1) f
+-- ["a"]
+--
+generate1 :: Int -> (Int -> a) -> CircularVector a
+generate1 n f = unsafeFromVector (Vector.generate (max n 1) f)
+
+-- | /O(n)/ Apply function n times to value. Zeroth element is original value.
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> iterateN 3 (+1) 0
+-- Just (CircularVector {vector = [0,1,2], rotation = 0})
+--
+-- >>> iterateN 0 (+1) 0
+-- Nothing
+--
+-- >>> iterateN (-1) (+1) 0
+-- Nothing
+--
+iterateN :: Int -> (a -> a) -> a -> Maybe (CircularVector a)
+iterateN n f a = fromVector' (Vector.iterateN n f a)
+
+-- | /O(n)/ Apply function n times to value. Zeroth element is original value.
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> iterateN1 3 (+1) 0
+-- CircularVector {vector = [0,1,2], rotation = 0}
+--
+-- >>> iterateN1 0 (+1) 0
+-- CircularVector {vector = [0], rotation = 0}
+--
+-- >>> iterateN1 (-1) (+1) 0
+-- CircularVector {vector = [0], rotation = 0}
+--
+iterateN1 :: Int -> (a -> a) -> a -> CircularVector a
+iterateN1 n f a = unsafeFromVector (Vector.iterateN (max n 1) f a)
+
+-- | /O(n)/ Execute the monadic action the given number of times and store
+-- the results in a circular vector.
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> replicateM @Maybe 3 (Just "a")
+-- Just (Just (CircularVector {vector = ["a","a","a"], rotation = 0}))
+--
+-- >>> replicateM @Maybe 3 Nothing
+-- Nothing
+--
+-- >>> replicateM @Maybe 0 (Just "a")
+-- Just Nothing
+--
+-- >>> replicateM @Maybe (-1) (Just "a")
+-- Just Nothing
+--
+replicateM :: Monad m => Int -> m a -> m (Maybe (CircularVector a))
+replicateM n a = fmap fromVector' (Vector.replicateM n a)
+
+-- | /O(n)/ Execute the monadic action the given number of times and store
+-- the results in a circular vector.
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> replicate1M @Maybe 3 (Just "a")
+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})
+--
+-- >>> replicate1M @Maybe 3 Nothing
+-- Nothing
+--
+-- >>> replicate1M @Maybe 0 (Just "a")
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+-- >>> replicate1M @Maybe (-1) (Just "a")
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+replicate1M :: Monad m => Int -> m a -> m (CircularVector a)
+replicate1M n a = fmap unsafeFromVector (Vector.replicateM (max n 1) a)
+
+-- | /O(n)/ Construct a circular vector of the given length by applying the monadic
+-- action to each index
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> generateM 3 (\i -> if i < 1 then ["a"] else ["b"])
+-- [Just (CircularVector {vector = ["a","b","b"], rotation = 0})]
+--
+-- >>> generateM @[] @Int 3 (const [])
+-- []
+--
+-- >>> generateM @[] @Int 0 (const [1])
+-- [Nothing]
+--
+-- >>> generateM @Maybe @Int (-1) (const Nothing)
+-- Just Nothing
+--
+generateM :: Monad m => Int -> (Int -> m a) -> m (Maybe (CircularVector a))
+generateM n f = fmap fromVector' (Vector.generateM n f)
+
+-- | /O(n)/ Construct a circular vector of the given length by applying the monadic
+-- action to each index
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> generate1M 3 (\i -> if i < 1 then Just "a" else Just "b")
+-- Just (CircularVector {vector = ["a","b","b"], rotation = 0})
+--
+-- >>> generate1M 3 (const [])
+-- []
+--
+-- >>> generate1M 0 (const $ Just 1)
+-- Just (CircularVector {vector = [1], rotation = 0})
+--
+-- >>> generate1M (-1) (const Nothing)
+-- Nothing
+--
+generate1M :: Monad m => Int -> (Int -> m a) -> m (CircularVector a)
+generate1M n f = fmap unsafeFromVector (Vector.generateM (max n 1) f)
+
+-- | /O(n)/ Apply monadic function n times to value. Zeroth element is
+-- original value.
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> iterateNM @Maybe 3 return "a"
+-- Just (Just (CircularVector {vector = ["a","a","a"], rotation = 0}))
+--
+-- >>> iterateNM @Maybe 3 (const Nothing) "a"
+-- Nothing
+--
+-- >>> iterateNM @Maybe 0 return "a"
+-- Just Nothing
+--
+iterateNM :: Monad m => Int -> (a -> m a) -> a -> m (Maybe (CircularVector a))
+iterateNM n f a = fmap fromVector' (Vector.iterateNM n f a)
+
+-- | /O(n)/ Apply monadic function n times to value. Zeroth element is
+-- original value.
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> iterateN1M @Maybe 3 return "a"
+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})
+--
+-- >>> iterateN1M @Maybe 3 (const Nothing) "a"
+-- Nothing
+--
+-- >>> iterateN1M @Maybe 0 return "a"
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+-- >>> iterateN1M @Maybe (-1) return "a"
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+iterateN1M :: Monad m => Int -> (a -> m a) -> a -> m (CircularVector a)
+iterateN1M n f a = fmap unsafeFromVector (Vector.iterateNM (max n 1) f a)
+
+-- | Execute the monadic action and freeze the resulting circular vector.
+--
+--   @since 0.1.2
+create :: (forall s. ST s (MVector.MVector s a)) -> Maybe (CircularVector a)
+create p = fromVector' (Vector.create p)
+
+-- | Execute the monadic action and freeze the resulting circular vector,
+-- bypassing emptiness checks.
+--
+-- The onus is on the caller to guarantee the created vector is non-empty.
+--
+--   @since 0.1.2
+unsafeCreate :: (forall s. ST s (MVector.MVector s a)) -> CircularVector a
+unsafeCreate p = unsafeFromVector (Vector.create p)
+
+-- | Execute the monadic action and freeze the resulting circular vector.
+--
+--   @since 0.1.2
+createT
+    :: Traversable t
+    => (forall s. ST s (t (MVector.MVector s a)))
+    -> t (Maybe (CircularVector a))
+createT p = fmap fromVector' (Vector.createT p)
+
+-- | Execute the monadic action and freeze the resulting circular vector.
+--
+-- The onus is on the caller to guarantee the created vector is non-empty.
+--
+--   @since 0.1.2
+unsafeCreateT
+    :: Traversable t
+    => (forall s. ST s (t (MVector.MVector s a)))
+    -> t (CircularVector a)
+unsafeCreateT p = fmap unsafeFromVector (Vector.createT p)
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the
+-- generator function to a seed. The generator function yields 'Just' the
+-- next element and the new seed or 'Nothing' if there are no more
+-- elements.
+--
+-- If an unfold does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+--
+-- >>> unfoldr (\b -> case b of "a" -> Just ("a", "b"); _ ->  Nothing) "a"
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+-- >>> unfoldr (const Nothing) "a"
+-- Nothing
+--
+unfoldr :: (b -> Maybe (a, b)) -> b -> Maybe (CircularVector a)
+unfoldr f b = fromVector' (Vector.unfoldr f b)
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the
+-- generator function to a seed and a first element.
+--
+-- This variant of 'unfoldr' guarantees the resulting vector is non-
+-- empty by supplying an initial element @a@.
+--
+--   @since 0.1.2
+--
+-- >>> unfoldr1 (\b -> case b of "a" -> Just ("a", "b"); _ ->  Nothing) "first" "a"
+-- CircularVector {vector = ["first","a"], rotation = 0}
+--
+-- >>> unfoldr1 (const Nothing) "first" "a"
+-- CircularVector {vector = ["first"], rotation = 0}
+--
+unfoldr1 :: (b -> Maybe (a, b)) -> a -> b -> CircularVector a
+unfoldr1 f a b = cons a (unsafeFromVector (Vector.unfoldr f b))
+
+-- | /O(n)/ Construct a circular vector with at most n elements by repeatedly
+-- applying the generator function to a seed. The generator function yields
+-- 'Just' the next element and the new seed or 'Nothing' if there are no
+-- more elements.
+--
+-- If an unfold does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+--
+-- >>> unfoldrN 3 (\b -> Just (b+1, b+1)) 0
+-- Just (CircularVector {vector = [1,2,3], rotation = 0})
+--
+-- >>> unfoldrN 3 (const Nothing) 0
+-- Nothing
+--
+-- >>> unfoldrN 0 (\b -> Just (b+1, b+1)) 0
+-- Nothing
+--
+unfoldrN :: Int -> (b -> Maybe (a, b)) -> b -> Maybe (CircularVector a)
+unfoldrN n f b = fromVector' (Vector.unfoldrN n f b)
+
+-- | /O(n)/ Construct a circular vector with at most n elements by repeatedly
+-- applying the generator function to a seed. The generator function yields
+-- 'Just' the next element and the new seed or 'Nothing' if there are no
+-- more elements.
+--
+-- This variant of 'unfoldrN' guarantees the resulting vector is non-
+-- empty by supplying an initial element @a@.
+--
+--   @since 0.1.2
+--
+-- >>> unfoldr1N 3 (\b -> Just (b+1, b+1)) 0 0
+-- CircularVector {vector = [0,1,2,3], rotation = 0}
+--
+-- >>> unfoldr1N 3 (const Nothing) 0 0
+-- CircularVector {vector = [0], rotation = 0}
+--
+-- >>> unfoldr1N 0 (\b -> Just (b+1, b+1)) 0 0
+-- CircularVector {vector = [0], rotation = 0}
+--
+unfoldr1N
+    :: Int
+    -> (b -> Maybe (a, b))
+    -> a
+    -> b
+    -> CircularVector a
+unfoldr1N n f a b = cons a (unsafeFromVector (Vector.unfoldrN n f b))
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator
+-- function to a seed. The generator function yields Just the next element
+-- and the new seed or Nothing if there are no more elements.
+--
+-- If an unfold does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+unfoldrM
+    :: Monad m
+    => (b -> m (Maybe (a, b)))
+    -> b
+    -> m (Maybe (CircularVector a))
+unfoldrM f b = fmap fromVector' (Vector.unfoldrM f b)
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator
+-- function to a seed. The generator function yields Just the next element
+-- and the new seed or Nothing if there are no more elements.
+--
+-- This variant of 'unfoldrM' guarantees the resulting vector is non-
+-- empty by supplying an initial element @a@.
+--
+--   @since 0.1.2
+unfoldr1M
+    :: Monad m
+    => (b -> m (Maybe (a, b)))
+    -> a
+    -> b
+    -> m (CircularVector a)
+unfoldr1M f a b = fmap (cons a . unsafeFromVector) (Vector.unfoldrM f b)
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator
+-- function to a seed. The generator function yields Just the next element and
+-- the new seed or Nothing if there are no more elements.
+--
+-- If an unfold does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+unfoldrNM
+    :: Monad m
+    => Int
+    -> (b -> m (Maybe (a, b)))
+    -> b
+    -> m (Maybe (CircularVector a))
+unfoldrNM n f b = fmap fromVector' (Vector.unfoldrNM n f b)
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator
+-- function to a seed. The generator function yields Just the next element and
+-- the new seed or Nothing if there are no more elements.
+--
+-- This variant of 'unfoldrNM' guarantees the resulting vector is non-
+-- empty by supplying an initial element @a@.
+--
+--   @since 0.1.2
+unfoldr1NM
+    :: Monad m
+    => Int
+    -> (b -> m (Maybe (a, b)))
+    -> a
+    -> b
+    -> m (CircularVector a)
+unfoldr1NM n f a b = fmap (cons a . unsafeFromVector) (Vector.unfoldrNM n f b)
+
+-- | /O(n)/ Construct a circular vector with n elements by repeatedly applying the
+-- generator function to the already constructed part of the vector.
+--
+-- If 'constructN' does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+constructN :: Int -> (Vector a -> a) -> Maybe (CircularVector a)
+constructN n f = fromVector' (Vector.constructN n f)
+
+-- | /O(n)/ Construct a circular vector with n elements from right to left by repeatedly
+-- applying the generator function to the already constructed part of the vector.
+--
+-- If 'constructrN' does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+constructrN :: Int -> (Vector a -> a) -> Maybe (CircularVector a)
+constructrN n f = fromVector' (Vector.constructrN n f)
+
+-- | /O(n)/ Yield a circular vector of the given length containing the
+-- values x, x+1 etc. This operation is usually more efficient than
+-- 'enumFromTo'.
+--
+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,
+-- otherwise, 'Just' containing a circular vector.
+--
+--   @since 0.1.2
+enumFromN :: Num a => a -> Int -> Maybe (CircularVector a)
+enumFromN a n = fromVector' (Vector.enumFromN a n)
+
+-- | /O(n)/ Yield a circular vector of length @max n 1@ containing the
+-- values x, x+1 etc. This operation is usually more efficient than
+-- 'enumFromTo'.
+--
+--   @since 0.1.2
+enumFromN1 :: Num a => a -> Int -> CircularVector a
+enumFromN1 a n = unsafeFromVector (Vector.enumFromN a (max n 1))
+
+-- | /O(n)/ Yield a circular vector of the given length containing the
+-- values x, x+y, x+y+y etc. This operations is usually more efficient than
+-- 'enumFromThenTo'.
+--
+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,
+-- otherwise, 'Just' containing a circular vector.
+--
+--   @since 0.1.2
+enumFromStepN :: Num a => a -> a -> Int -> Maybe (CircularVector a)
+enumFromStepN a0 a1 n = fromVector' (Vector.enumFromStepN a0 a1 n)
+
+-- | /O(n)/ Yield a circular vector of length @max n 1@ containing the
+-- values x, x+y, x+y+y etc. This operations is usually more efficient than
+-- 'enumFromThenTo'.
+--
+--   @since 0.1.2
+enumFromStepN1 :: Num a => a -> a -> Int -> CircularVector a
+enumFromStepN1 a0 a1 n = unsafeFromVector (Vector.enumFromStepN a0 a1 (max n 1))
+
+-- | /O(n)/ Enumerate values from x to y.
+--
+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,
+-- otherwise, 'Just' containing a circular vector.
+--
+-- /WARNING/: This operation can be very inefficient. If at all possible,
+-- use 'enumFromN' instead.
+--
+--
+--   @since 0.1.2
+enumFromTo :: Enum a => a -> a -> Maybe (CircularVector a)
+enumFromTo a0 a1 = fromVector' (Vector.enumFromTo a0 a1)
+
+-- | /O(n)/ Enumerate values from x to y with a specific step z.
+--
+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,
+-- otherwise, 'Just' containing a circular vector.
+--
+-- /WARNING/: This operation can be very inefficient. If at all possible,
+-- use 'enumFromStepN' instead.
+--
+--   @since 0.1.2
+enumFromThenTo :: Enum a => a -> a -> a -> Maybe (CircularVector a)
+enumFromThenTo a0 a1 a2 = fromVector' (Vector.enumFromThenTo a0 a1 a2)
+
+-- | /O(n)/ Prepend an element
+--
+--   @since 0.1.2
+--
+-- >>> cons 1 (unsafeFromList [2,3])
+-- CircularVector {vector = [1,2,3], rotation = 0}
+--
+cons :: a -> CircularVector a -> CircularVector a
+cons a cv = consV a (toVector cv)
+{-# INLINE cons #-}
+
+-- | /O(n)/ Prepend an element to a Vector
+--
+--   @since 0.1.2
+--
+-- >>> consV 1 (Vector.fromList [2,3])
+-- CircularVector {vector = [1,2,3], rotation = 0}
+--
+consV :: a -> Vector a -> CircularVector a
+consV a = fromVector . NonEmpty.consV a
+{-# INLINE consV #-}
+
+-- | /O(n)/ Append an element
+--
+--   @since 0.1.2
+--
+-- >>> snoc (unsafeFromList [1,2]) 3
+-- CircularVector {vector = [1,2,3], rotation = 0}
+--
+snoc :: CircularVector a -> a -> CircularVector a
+snoc = snocV . toVector
+
+-- | /O(n)/ Append an element to a Vector
+--
+--   @since 0.1.2
+--
+-- >>> snocV (Vector.fromList [1,2]) 3
+-- CircularVector {vector = [1,2,3], rotation = 0}
+--
+snocV :: Vector a -> a -> CircularVector a
+snocV as = fromVector . NonEmpty.snocV as
+
+-- | /O(m+n)/ Concatenate two circular vectors
+--
+--   @since 0.1.2
+--
+-- >>> (unsafeFromList [1..3]) ++ (unsafeFromList [4..6])
+-- CircularVector {vector = [1,2,3,4,5,6], rotation = 0}
+--
+(++) :: CircularVector a -> CircularVector a -> CircularVector a
+v ++ v' = fromVector (toNonEmptyVector v NonEmpty.++ toNonEmptyVector v')
+
+-- | /O(n)/ Concatenate all circular vectors in the list
+--
+-- If list is empty, 'Nothing' is returned, otherwise 'Just'
+-- containing the concatenated circular vectors
+--
+--   @since 0.1.2
+--
+-- >>> concat [(unsafeFromList [1..3]), (unsafeFromList [4..6])]
+-- Just (CircularVector {vector = [1,2,3,4,5,6], rotation = 0})
+--
+concat :: [CircularVector a] -> Maybe (CircularVector a)
+concat [] = Nothing
+concat (a:as) = Just (concat1 (a :| as))
+{-# INLINE concat #-}
+
+-- | O(n) Concatenate all circular vectors in a non-empty list.
+--
+--   @since 0.1.2
+--
+-- >>> concat1 ((unsafeFromList [1..3]) :| [(unsafeFromList [4..6])])
+-- CircularVector {vector = [1,2,3,4,5,6], rotation = 0}
+--
+concat1 :: NonEmpty (CircularVector a) -> CircularVector a
+concat1 = fromVector . NonEmpty.concat1 . fmap toNonEmptyVector
+
+-- | /O(n)/ Map a function over a circular vector.
+--
+--   @since 0.1.2
+--
+-- >>> map (+1) $ unsafeFromList [1..3]
+-- CircularVector {vector = [2,3,4], rotation = 0}
+--
+map :: (a -> b) -> CircularVector a -> CircularVector b
+map f (CircularVector v rot) = CircularVector (NonEmpty.map f v) rot
+
+-- | /O(n)/ Apply a function to every element of a circular vector and
+-- its index.
+--
+--   @since 0.1.2
+--
+-- >>> imap (\i a -> if i == 2 then a+1 else a+0) $ unsafeFromList [1..3]
+-- CircularVector {vector = [1,2,4], rotation = 0}
+--
+imap :: (Int -> a -> b) -> CircularVector a -> CircularVector b
+imap f = fromVector . NonEmpty.imap f . toNonEmptyVector
+
+-- | Map a function over a circular vector and concatenate the results.
+--
+--   @since 0.1.2
+--
+-- >>> concatMap (\a -> unsafeFromList [a,a]) (unsafeFromList [1,2,3])
+-- CircularVector {vector = [1,1,2,2,3,3], rotation = 0}
+--
+concatMap
+    :: (a -> CircularVector b)
+    -> CircularVector a
+    -> CircularVector b
+concatMap f = fromVector . NonEmpty.concatMap (toNonEmptyVector . f) . toNonEmptyVector
+
+-- | /O(n)/ Apply the monadic action to all elements of the circular
+-- vector, yielding circular vector of results.
+--
+--   @since 0.1.2
+--
+-- >>> mapM Just (unsafeFromList [1..3])
+-- Just (CircularVector {vector = [1,2,3], rotation = 0})
+--
+-- >>> mapM (const Nothing) (unsafeFromList [1..3])
+-- Nothing
+--
+mapM :: Monad m => (a -> m b) -> CircularVector a -> m (CircularVector b)
+mapM f = fmap fromVector . NonEmpty.mapM f . toNonEmptyVector
+
+-- | /O(n)/ Apply the monadic action to every element of a circular
+-- vector and its index, yielding a circular vector of results.
+--
+--   @since 0.1.2
+--
+-- >>> imapM (\i a -> if i == 1 then Just a else Just 0) (unsafeFromList [1..3])
+-- Just (CircularVector {vector = [0,2,0], rotation = 0})
+--
+-- >>> imapM (\_ _ -> Nothing) (unsafeFromList [1..3])
+-- Nothing
+--
+imapM
+    :: Monad m
+    => (Int -> a -> m b)
+    -> CircularVector a
+    -> m (CircularVector b)
+imapM f = fmap fromVector . NonEmpty.imapM f . toNonEmptyVector
+
+-- | /O(n)/ Apply the monadic action to all elements of a circular vector
+-- and ignore the results.
+--
+--   @since 0.1.2
+--
+-- >>> mapM_ (const $ Just ()) (unsafeFromList [1..3])
+-- Just ()
+--
+-- >>> mapM_ (const Nothing) (unsafeFromList [1..3])
+-- Nothing
+--
+mapM_ :: Monad m => (a -> m b) -> CircularVector a -> m ()
+mapM_ f = NonEmpty.mapM_ f . toNonEmptyVector
+
+-- | /O(n)/ Apply the monadic action to every element of a circular
+-- vector and its index, ignoring the results
+--
+--   @since 0.1.2
+--
+-- >>> imapM_ (\i a -> if i == 1 then print a else putStrLn "0") (unsafeFromList [1..3])
+-- 0
+-- 2
+-- 0
+--
+-- >>> imapM_ (\_ _ -> Nothing) (unsafeFromList [1..3])
+-- Nothing
+--
+imapM_ :: Monad m => (Int -> a -> m b) -> CircularVector a -> m ()
+imapM_ f = NonEmpty.imapM_ f . toNonEmptyVector
+
+-- | /O(n)/ Apply the monadic action to all elements of the circular
+-- vector, yielding a circular vector of results.
+--
+-- Equivalent to @flip 'mapM'@.
+--
+--   @since 0.1.2
+forM :: Monad m => CircularVector a -> (a -> m b) -> m (CircularVector b)
+forM cv f = fromVector <$> NonEmpty.forM (toNonEmptyVector cv) f
+
+-- | /O(n)/ Apply the monadic action to all elements of a circular
+-- vector and ignore the results.
+--
+-- Equivalent to @flip 'mapM_'@.
+--
+--   @since 0.1.2
+forM_ :: Monad m => CircularVector a -> (a -> m b) -> m ()
+forM_ cv f = NonEmpty.forM_ (toNonEmptyVector cv) f
+
+-- | /O(n)/ Drop repeated adjacent elements.
+--
+-- >>> toList $ uniq $ unsafeFromList [1,1,2,2,3,3,1]
+-- [1,2,3]
+--
+-- >>> toList $ uniq $ unsafeFromList [1,2,3,1]
+-- [1,2,3]
+--
+-- >>> toList $ uniq $ unsafeFromList [1]
+-- [1]
+uniq :: Eq a => CircularVector a -> CircularVector a
+uniq = fromVector . trim . NonEmpty.uniq . toNonEmptyVector
+  where
+    trim v
+      | Foldable.length v == 1 || NonEmpty.head v /= NonEmpty.last v
+        = v
+      | otherwise
+        = trim (NonEmpty.unsafeFromVector $ NonEmpty.init v)
+
+-- | /O(n)/ Drop elements when predicate returns Nothing
+--
+-- If no elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> mapMaybe (\a -> if a == 2 then Nothing else Just a) (unsafeFromList [1..3])
+-- [1,3]
+mapMaybe
+    :: (a -> Maybe b)
+    -> CircularVector a
+    -> Vector b
+mapMaybe f = NonEmpty.mapMaybe f . toNonEmptyVector
+
+-- | /O(n)/ Drop elements when predicate, applied to index and value, returns Nothing
+--
+-- If no elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> imapMaybe (\i a -> if a == 2 || i == 2 then Nothing else Just a) (unsafeFromList [1..3])
+-- [1]
+--
+imapMaybe
+    :: (Int -> a -> Maybe b)
+    -> CircularVector a
+    -> Vector b
+imapMaybe f = NonEmpty.imapMaybe f . toNonEmptyVector
+
+-- | /O(n)/ Yield the longest prefix of elements satisfying the predicate
+-- without copying.
+--
+-- If no elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> takeWhile (/= 3) (unsafeFromList [1..3])
+-- [1,2]
+--
+takeWhile :: (a -> Bool) -> CircularVector a -> Vector a
+takeWhile f = NonEmpty.takeWhile f . toNonEmptyVector
+
+-- | /O(n)/ Drop the longest prefix of elements that satisfy the predicate
+-- without copying.
+--
+-- If all elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> dropWhile (/= 3) (unsafeFromList [1..3])
+-- [3]
+--
+dropWhile :: (a -> Bool) -> CircularVector a -> Vector a
+dropWhile f = NonEmpty.dropWhile f . toNonEmptyVector
+
+-- | /O(n)/ Split the circular vector in two parts, the first one
+-- containing those elements that satisfy the predicate and the second
+-- one those that don't. The relative order of the elements is preserved
+-- at the cost of a sometimes reduced performance compared to
+-- 'unstablePartition'.
+--
+-- If all or no elements satisfy the predicate, one of the resulting vectors
+-- may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> partition (< 3) (unsafeFromList [1..5])
+-- ([1,2],[3,4,5])
+--
+partition :: (a -> Bool) -> CircularVector a -> (Vector a, Vector a)
+partition f = NonEmpty.partition f . toNonEmptyVector
+
+-- | /O(n)/ Split the circular vector in two parts, the first one
+-- containing those elements that satisfy the predicate and the second
+-- one those that don't. The order of the elements is not preserved but
+-- the operation is often faster than 'partition'.
+--
+-- If all or no elements satisfy the predicate, one of the resulting vectors
+-- may be empty.
+--
+--   @since 0.1.2
+unstablePartition
+    :: (a -> Bool)
+    -> CircularVector a
+    -> (Vector a, Vector a)
+unstablePartition f = NonEmpty.unstablePartition f . toNonEmptyVector
+
+-- | /O(n)/ Split the circular vector into the longest prefix of elements
+-- that satisfy the predicate and the rest without copying.
+--
+-- If all or no elements satisfy the predicate, one of the resulting vectors
+-- may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> span (== 1) (unsafeFromList [1,1,2,3,1])
+-- ([1,1],[2,3,1])
+--
+span :: (a -> Bool) -> CircularVector a -> (Vector a, Vector a)
+span f = NonEmpty.span f . toNonEmptyVector
+
+-- | /O(n)/ Split the circular vector into the longest prefix of elements that do not
+-- satisfy the predicate and the rest without copying.
+--
+-- If all or no elements satisfy the predicate, one of the resulting vectors
+-- may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> break (== 2) (unsafeFromList [1,1,2,3,1])
+-- ([1,1],[2,3,1])
+--
+break :: (a -> Bool) -> CircularVector a -> (Vector a, Vector a)
+break f = NonEmpty.break f . toNonEmptyVector
+
+-- | /O(n)/ Check if the circular vector contains an element
+--
+--   @since 0.1.2
+--
+-- >>> elem 1 $ unsafeFromList [1..3]
+-- True
+-- >>> elem 4 $ unsafeFromList [1..3]
+-- False
+--
+elem :: Eq a => a -> CircularVector a -> Bool
+elem a = NonEmpty.elem a . toNonEmptyVector
+
+-- | /O(n)/ Check if the circular vector does not contain an element
+-- (inverse of 'elem')
+--
+--   @since 0.1.2
+--
+-- >>> notElem 1 $ unsafeFromList [1..3]
+-- False
+--
+-- >>> notElem 4 $ unsafeFromList [1..3]
+-- True
+--
+notElem :: Eq a => a -> CircularVector a -> Bool
+notElem a = NonEmpty.notElem a . toNonEmptyVector
+
+-- | /O(n)/ Yield 'Just' the first element matching the predicate or
+-- 'Nothing' if no such element exists.
+--
+--   @since 0.1.2
+--
+-- >>> find (< 2) $ unsafeFromList [1..3]
+-- Just 1
+--
+-- >>> find (< 0) $ unsafeFromList [1..3]
+-- Nothing
+--
+find :: (a -> Bool) -> CircularVector a -> Maybe a
+find f = NonEmpty.find f . toNonEmptyVector
+
+-- | /O(n)/ Yield 'Just' the index of the first element matching the
+-- predicate or 'Nothing' if no such element exists.
+--
+--   @since 0.1.2
+--
+-- >>> findIndex (< 2) $ unsafeFromList [1..3]
+-- Just 0
+--
+-- >>> findIndex (< 0) $ unsafeFromList [1..3]
+-- Nothing
+--
+-- >>> findIndex (==1) $ rotateRight 1 (unsafeFromList [1..3])
+-- Just 2
+findIndex :: (a -> Bool) -> CircularVector a -> Maybe Int
+findIndex f = NonEmpty.findIndex f . toNonEmptyVector
+
+-- | /O(n)/ Yield the indices of elements satisfying the predicate in
+-- ascending order.
+--
+--   @since 0.1.2
+--
+-- >>> findIndices (< 3) $ unsafeFromList [1..3]
+-- [0,1]
+--
+-- >>> findIndices (< 0) $ unsafeFromList [1..3]
+-- []
+--
+findIndices :: (a -> Bool) -> CircularVector a -> Vector Int
+findIndices f = NonEmpty.findIndices f . toNonEmptyVector
+
+-- | /O(n)/ Yield 'Just' the index of the first occurence of the given
+-- element or 'Nothing' if the circular vector does not contain the
+-- element. This is a specialised version of 'findIndex'.
+--
+--   @since 0.1.2
+--
+-- >>> elemIndex 1 $ unsafeFromList [1..3]
+-- Just 0
+--
+-- >>> elemIndex 0 $ unsafeFromList [1..3]
+-- Nothing
+--
+elemIndex :: Eq a => a -> CircularVector a -> Maybe Int
+elemIndex a = NonEmpty.elemIndex a . toNonEmptyVector
+
+-- | /O(n)/ Yield the indices of all occurences of the given element in
+-- ascending order. This is a specialised version of 'findIndices'.
+--
+--   @since 0.1.2
+--
+-- >>> elemIndices 1 $ unsafeFromList [1,2,3,1]
+-- [0,3]
+--
+-- >>> elemIndices 0 $ unsafeFromList [1..3]
+-- []
+--
+elemIndices :: Eq a => a -> CircularVector a -> Vector Int
+elemIndices a = NonEmpty.elemIndices a . toNonEmptyVector
+
+-- | /O(n)/ Drop elements that do not satisfy the predicate which is
+-- applied to values and their indices.
+--
+-- If no elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> ifilter (\i a -> if a == 2 || i == 0 then False else True) (unsafeFromList [1..3])
+-- [3]
+--
+-- >>> ifilter (\_ _ -> False) (unsafeFromList [1..3])
+-- []
+--
+ifilter
+    :: (Int -> a -> Bool)
+    -> CircularVector a
+    -> Vector a
+ifilter f = NonEmpty.ifilter f . toNonEmptyVector
+
+-- | /O(n)/ Drop elements that do not satisfy the monadic predicate.
+--
+-- If no elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> filterM (\a -> if a == 2 then Just False else Just True) (unsafeFromList [1..3])
+-- Just [1,3]
+--
+-- >>> filterM (\a -> if a == 2 then Nothing else Just True) (unsafeFromList [1..3])
+-- Nothing
+--
+-- >>> filterM (const $ Just False) (unsafeFromList [1..3])
+-- Just []
+--
+filterM
+    :: Monad m
+    => (a -> m Bool)
+    -> CircularVector a
+    -> m (Vector a)
+filterM f = NonEmpty.filterM f . toNonEmptyVector
+
+-- | /O(n)/ Drop elements that do not satisfy the monadic predicate that is
+-- a function of index and value.
+--
+-- If no elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> ifilterM (\i a -> if a == 2 || i == 0 then Just False else Just True) (unsafeFromList [1..3])
+-- Just [3]
+--
+-- >>> ifilterM (\i a -> if a == 2 || i == 0 then Nothing else Just True) (unsafeFromList [1..3])
+-- Nothing
+--
+-- >>> ifilterM (\_ _ -> Just False) (unsafeFromList [1..3])
+-- Just []
+--
+ifilterM
+    :: Monad m
+    => (Int -> a -> m Bool)
+    -> CircularVector a
+    -> m (Vector a)
+ifilterM f = NonEmpty.ifilterM f . toNonEmptyVector
+
+-- | /O(n)/ Yield the circular vector obtained by replacing each element
+-- @i@ of the circular index vector by @xs'!'i@. This is equivalent to
+-- @'map' (xs'!') is@ but is often much more efficient.
+--
+--   @since 0.1.2
+--
+-- >>> toList $ backpermute (unsafeFromList [1..3]) (unsafeFromList [2,0])
+-- [3,1]
+--
+backpermute :: CircularVector a -> CircularVector Int -> CircularVector a
+backpermute v i = fromVector $ NonEmpty.backpermute (toNonEmptyVector v) (toNonEmptyVector i)
+
+-- | Same as 'backpermute' but without bounds checking.
+--
+--   @since 0.1.2
+unsafeBackpermute
+    :: CircularVector a
+    -> CircularVector Int
+    -> CircularVector a
+unsafeBackpermute v i = fromVector (NonEmpty.unsafeBackpermute (toNonEmptyVector v) (toNonEmptyVector i))
+
+-- | Apply a destructive operation to a circular vector. The operation
+-- will be performed in place if it is safe to do so and will modify a
+-- copy of the circular vector otherwise.
+--
+--   @since 0.1.2
+modify
+    :: (forall s. MVector.MVector s a -> ST s ())
+    -> CircularVector a
+    -> CircularVector a
+modify p = fromVector . NonEmpty.modify p . toNonEmptyVector
diff --git a/src/Data/Vector/Circular/Generic.hs b/src/Data/Vector/Circular/Generic.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Vector/Circular/Generic.hs
@@ -0,0 +1,1769 @@
+{-# language
+    BangPatterns
+  , CPP
+  , DeriveAnyClass
+  , DeriveFunctor
+  , DeriveGeneric
+  , DerivingStrategies
+  , InstanceSigs
+  , ScopedTypeVariables
+  , TemplateHaskell
+  , TypeApplications
+  , RankNTypes
+  , FlexibleContexts
+#-}
+
+module Data.Vector.Circular.Generic
+  ( -- * Types
+    CircularVector(..)
+
+    -- * Construction
+    -- ** Initialization
+  , singleton
+  , replicate
+  , replicate1
+  , generate
+  , generate1
+  , iterateN
+  , iterateN1
+    -- ** Monad Initialization
+  , replicateM
+  , replicate1M
+  , generateM
+  , generate1M
+  , iterateNM
+  , iterateN1M
+  , create
+  , unsafeCreate
+  , createT
+  , unsafeCreateT
+    -- ** Unfolding
+  , unfoldr
+  , unfoldr1
+  , unfoldrN
+  , unfoldr1N
+  , unfoldrM
+  , unfoldr1M
+  , unfoldrNM
+  , unfoldr1NM
+  , constructN
+  , constructrN
+    -- ** Enumeration
+  , enumFromN
+  , enumFromN1
+  , enumFromStepN
+  , enumFromStepN1
+  , enumFromTo
+  , enumFromThenTo
+    -- ** Concatenation
+  , cons
+  , consV
+  , snoc
+  , snocV
+  , (Data.Vector.Circular.Generic.++)
+  , concat
+  , concat1
+    -- ** Restricting memory usage
+  , force
+
+    -- ** Template Haskell
+  -- , vec
+
+    -- * Conversion
+  , toVector
+  , fromVector
+  , unsafeFromVector
+  , toNonEmptyVector
+  , toList
+  , fromList
+  , fromListN
+  , unsafeFromList
+  , unsafeFromListN
+
+    -- * Rotation
+  , rotateLeft
+  , rotateRight
+
+    -- * Comparisons
+  , equivalent
+  , canonise
+  , leastRotation
+
+    -- * Folds
+  , foldMap
+  , foldMap'
+  , foldr
+  , foldl
+  , foldr'
+  , foldl'
+  , foldr1
+  , foldl1
+  , foldMap1
+  , foldMap1'
+  , toNonEmpty
+
+    -- * Specialized folds
+  , all
+  , any
+  , and
+  , or
+  , sum
+  , product
+  , maximum
+  , maximumBy
+  , minimum
+  , minimumBy
+  , rotateToMinimumBy
+  , rotateToMaximumBy
+
+    -- * Elementwise operations
+    -- ** Indexing
+  , index
+  , head
+  , last
+
+    -- ** Mapping
+  , map
+  , imap
+  , concatMap
+
+    -- ** Monadic mapping
+  , mapM
+  , imapM
+  , mapM_
+  , imapM_
+  , forM
+  , forM_
+
+    -- ** Zipping
+  , zipWith
+  , zipWith3
+  , zip
+  , zip3
+
+    -- ** Unzipping
+  , unzip
+  , unzip3
+
+    -- ** Filtering
+  , uniq
+  , mapMaybe
+  , imapMaybe
+  , filter
+  , ifilter
+  , filterM
+  -- , ifilterM -- Not in Data.Vector.Generic
+  , takeWhile
+  , dropWhile
+
+    -- * Partitioning
+  , partition
+  , unstablePartition
+  , span
+  , break
+
+    -- * Searching
+  , elem
+  , notElem
+  , find
+  , findIndex
+  , findIndices
+  , elemIndex
+  , elemIndices
+
+    -- * Permutations
+  , reverse
+  , backpermute
+  , unsafeBackpermute
+
+    -- * Safe destructive updates
+  , modify
+
+    -- * Monadic Sequencing
+  , sequence
+  , sequence_
+  ) where
+
+import qualified Control.Monad (when, forM_)
+import Control.Monad.ST (ST, runST)
+import Control.DeepSeq
+#if MIN_VERSION_base(4,13,0)
+-- import Data.Foldable (foldMap')
+#endif /* MIN_VERSION_base(4,13,0) */
+import Data.List.NonEmpty (NonEmpty((:|)))
+import qualified Data.List.NonEmpty as NonEmptyList
+import Data.Primitive.MutVar ( newMutVar, readMutVar, writeMutVar )
+import Data.Vector.NonEmpty (NonEmptyVector)
+import GHC.Base (modInt)
+import GHC.Generics (Generic)
+import Prelude hiding (head, length, last, map, concat, takeWhile
+                      ,dropWhile, span, break, elem, notElem, reverse
+                      ,mapM, mapM_, foldMap, foldr
+                      ,foldl, foldr1, foldl1, all, any, and, or, sum
+                      ,product, maximum, minimum, concatMap
+                      ,zipWith, zipWith3, zip, zip3, replicate, enumFromTo
+                      ,enumFromThenTo, (++))
+import Language.Haskell.TH.Syntax
+import qualified Data.Vector.Mutable as MVector
+import qualified Data.Vector.NonEmpty as NonEmpty
+import qualified Data.Vector.Generic as G
+import qualified Prelude
+import Data.Monoid
+import Data.Coerce
+import Data.Maybe ( fromMaybe )
+
+-- $setup
+-- >>> import Data.Vector (Vector)
+-- >>> import qualified Data.Vector
+
+
+-- | A circular, immutable vector. This type is equivalent to
+--   @'Data.List.cycle' xs@ for some finite, nonempty @xs@, but
+--   with /O(1)/ access and /O(1)/ rotations. Indexing
+--   into this type is always total.
+data CircularVector v a = CircularVector
+  { vector :: !(v a)
+  , rotation :: {-# UNPACK #-} !Int
+  }
+  deriving stock
+    ( Functor -- ^ since 0.1.2
+    , Generic -- ^ @since 0.1.2
+    , Ord     -- ^ since 0.1.2
+    , Read    -- ^ since 0.1.2
+    , Show    -- ^ since 0.1.2
+    )
+  deriving anyclass
+    ( NFData -- ^ @since 0.1.2
+    )
+
+-- | @since 0.1.2
+-- instance Traversable (CircularVector v) where
+--   traverse :: (Applicative f) => (a -> f b) -> CircularVector a -> f (CircularVector b)
+--   traverse f (CircularVector v rot) =
+--     CircularVector <$> traverse f v <*> pure rot
+
+-- | since 0.1.2
+instance (G.Vector v a, Eq a) => Eq (CircularVector v a) where
+  (==) :: CircularVector v a -> CircularVector v a -> Bool
+  a == b = toVector a `G.eq` toVector b
+
+-- | @since 0.1.2
+-- instance Eq2 CircularVector where
+--   liftEq2 :: (a -> b -> Bool) -> CircularVector v a -> CircularVector v b -> Bool
+--   liftEq2 eq c0@(CircularVector x rx) c1@(CircularVector y ry)
+--     | G.length x /= G.length y = False
+--     | rx == ry = liftEq eq x y
+--     | otherwise = getAll $ flip Prelude.foldMap [0..NonEmpty.length x-1] $ \i ->
+--         All (index c0 i `eq` index c1 i)
+
+-- | @since 0.1.2
+-- instance Ord1 CircularVector where
+--   liftCompare :: (a -> b -> Ordering) -> CircularVector a -> CircularVector b -> Ordering
+--   liftCompare cmp (CircularVector x rx) (CircularVector y ry)
+--     = liftCompare cmp x y <> compare rx ry
+
+-- | @since 0.1.2
+-- instance Show1 CircularVector where
+--   liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> CircularVector a -> ShowS
+--   liftShowsPrec sp sl d (CircularVector x rx) =
+--     showsBinaryWith (liftShowsPrec sp sl) showsPrec "CircularVector" d x rx
+
+-- | @since 0.1.2
+-- instance Read1 CircularVector where
+--   liftReadPrec rp rl = readData $
+--     readBinaryWith (liftReadPrec rp rl) readPrec "CircularVector" CircularVector
+--   liftReadListPrec = liftReadListPrecDefault
+
+-- | The 'Semigroup' @('<>')@ operation behaves by un-rolling
+--   the two vectors so that their rotation is 0, concatenating
+--   them, returning a new vector with a 0-rotation.
+--
+--   since 0.1.2
+instance (G.Vector v a) => Semigroup (CircularVector v a) where
+  (<>) :: CircularVector v a -> CircularVector v a -> CircularVector v a
+  lhs <> rhs = CircularVector v 0
+    where
+      szLhs = length lhs
+      szRhs = length rhs
+      sz = szLhs + szRhs
+      v = G.generate sz
+            $ \ix -> if ix < szLhs
+                then index lhs ix
+                else index rhs (ix - szLhs)
+  {-# inline (<>) #-}
+
+-- | since 0.1.2
+-- instance Foldable (CircularVector v) where
+--   foldMap :: Monoid m => (a -> m) -> CircularVector v a -> m
+--   foldMap = Data.Vector.Circular.Generic.foldMap
+--   {-# inline foldMap #-}
+
+-- #if MIN_VERSION_base(4,13,0)
+--   foldMap' :: Monoid m => (a -> m) -> CircularVector a -> m
+--   foldMap' = Data.Vector.Circular.Generic.foldMap'
+--   {-# inline foldMap' #-}
+-- #endif /* MIN_VERSION_base(4,13,0) */
+
+--   null :: CircularVector a -> Bool
+--   null _ = False -- nonempty structure is always not null
+--   {-# inline null #-}
+
+--   length :: CircularVector a -> Int
+--   length = Data.Vector.Circular.Generic.length
+--   {-# inline length #-}
+
+-- | since 0.1.2
+-- instance Foldable1 CircularVector where
+--   foldMap1 :: Semigroup m => (a -> m) -> CircularVector a -> m
+--   foldMap1 = Data.Vector.Circular.Generic.foldMap1
+--   {-# inline foldMap1 #-}
+
+-- FIXME: This instance is probably broken.
+-- | since 0.1.2
+instance Lift a => Lift (CircularVector v a) where
+  lift c = do
+    v <- [|vector c|]
+    r <- [|rotation c|]
+    pure $ ConE ''CircularVector
+      `AppE` v
+      `AppE` r
+#if MIN_VERSION_template_haskell(2,16,0)
+  liftTyped = unsafeTExpCoerce . lift
+#endif /* MIN_VERSION_template_haskell(2,16,0) */
+
+-- | Get the length of a 'CircularVector'.
+--
+--   since 0.1.2
+length :: G.Vector v a => CircularVector v a -> Int
+length (CircularVector v _) = G.length v
+{-# inline length #-}
+
+-- | Lazily-accumulating monoidal fold over a 'CircularVector'.
+--   since 0.1.2
+foldMap :: (Monoid m, G.Vector v a) => (a -> m) -> CircularVector v a -> m
+foldMap f = \v ->
+  let len = Data.Vector.Circular.Generic.length v
+      go !ix
+        | ix < len = f (index v ix) <> go (ix + 1)
+        | otherwise = mempty
+  in go 0
+{-# inline foldMap #-}
+
+
+
+-- | Strictly-accumulating monoidal fold over a 'CircularVector'.
+--
+--   since 0.1.2
+foldMap' :: (Monoid m, G.Vector v a) => (a -> m) -> CircularVector v a -> m
+foldMap' f = \v ->
+  let len = Data.Vector.Circular.Generic.length v
+      go !ix !acc
+        | ix < len = go (ix + 1) (acc <> f (index v ix))
+        | otherwise = acc
+  in go 0 mempty
+{-# inline foldMap' #-}
+
+(#.) :: Coercible b c => (b -> c) -> (a -> b) -> (a -> c)
+(#.) _f = coerce
+{-# INLINE (#.) #-}
+
+-- | since 0.1.2
+foldr :: G.Vector v a => (a -> b -> b) -> b -> CircularVector v a -> b
+foldr f z t = appEndo (foldMap (Endo #. f) t) z
+
+-- -- | since 0.1.2
+foldl :: G.Vector v a => (b -> a -> b) -> b -> CircularVector v a -> b
+foldl f z t = appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z
+
+-- -- | since 0.1.2
+foldr' :: G.Vector v a => (a -> b -> b) -> b -> CircularVector v a -> b
+foldr' f z0 xs = foldl f' id xs z0
+  where f' k x z = k $! f x z
+
+-- -- | since 0.1.2
+foldl' :: G.Vector v a => (b -> a -> b) -> b -> CircularVector v a -> b
+foldl' f z0 xs = foldr f' id xs z0
+      where f' x k z = k $! f z x
+
+-- -- | since 0.1.2
+foldr1 :: G.Vector v a => (a -> a -> a) -> CircularVector v a -> a
+foldr1 f xs = fromMaybe (errorWithoutStackTrace "foldr1: empty structure")
+                    (foldr mf Nothing xs)
+      where
+        mf x m = Just (case m of
+                         Nothing -> x
+                         Just y  -> f x y)
+
+-- -- | since 0.1.2
+foldl1 :: G.Vector v a => (a -> a -> a) -> CircularVector v a -> a
+foldl1 f xs = fromMaybe (errorWithoutStackTrace "foldl1: empty structure")
+                    (foldl mf Nothing xs)
+      where
+        mf m y = Just (case m of
+                         Nothing -> y
+                         Just x  -> f x y)
+
+-- | since 0.1.2
+toNonEmpty :: G.Vector v a => CircularVector v a -> NonEmpty a
+toNonEmpty = NonEmptyList.fromList . toList
+
+-- | Lazily-accumulating semigroupoidal fold over
+--   a 'CircularVector'.
+--
+--   since 0.1.2
+foldMap1 :: (G.Vector v a, Semigroup m) => (a -> m) -> CircularVector v a -> m
+foldMap1 f = \v ->
+  let len = Data.Vector.Circular.Generic.length v
+      go !ix
+        | ix < len-1 = f (index v ix) <> go (ix + 1)
+        | otherwise  = f (last v)
+  in go 0
+{-# inline foldMap1 #-}
+
+-- | Strictly-accumulating semigroupoidal fold over
+--   a 'CircularVector'.
+--
+--   since 0.1.2
+foldMap1' :: (G.Vector v a, Semigroup m) => (a -> m) -> CircularVector v a -> m
+foldMap1' f = \v ->
+  let len = Data.Vector.Circular.Generic.length v
+      go !ix !acc
+        | ix < len = go (ix + 1) (acc <> f (index v ix))
+        | otherwise = acc
+  in go 1 (f (head v))
+{-# inline foldMap1' #-}
+
+-- | /O(n)/ Construct a 'Vector' from a 'CircularVector'.
+--
+--   since 0.1.2
+toVector :: G.Vector v a => CircularVector v a -> v a
+toVector v = G.generate (length v) (index v)
+
+-- | /O(n)/ Construct a 'NonEmptyVector' from a 'CircularVector'.
+--
+--   @since 0.1.2
+toNonEmptyVector :: G.Vector v a => CircularVector v a -> NonEmptyVector a
+toNonEmptyVector v = NonEmpty.generate1 (length v) (index v)
+
+-- | /O(1)/ Construct a 'CircularVector' from a vector.
+--
+--   since 0.1.2
+fromVector :: G.Vector v a => v a -> Maybe (CircularVector v a)
+fromVector v | G.null v = Nothing
+fromVector v = Just (CircularVector v 0)
+{-# inline fromVector #-}
+
+-- | /O(1)/ Construct a 'CircularVector' from a 'Vector'.
+--
+--   Calls @'error'@ if the input vector is empty.
+--
+--   since 0.1.2
+unsafeFromVector :: G.Vector v a => v a -> CircularVector v a
+unsafeFromVector v = CircularVector v 0
+
+-- | /O(n)/ Convert from a circular vector to a list.
+--
+--
+-- >>> let nev = unsafeFromList @Vector [1..3] in toList nev
+-- [1,2,3]
+--
+--   @since 0.1.2
+toList :: G.Vector v a => CircularVector v a -> [a]
+toList = G.toList . toVector
+
+-- | /O(n)/ Construct a 'CircularVector' from a list.
+--
+--   since 0.1.2
+fromList :: G.Vector v a => [a] -> Maybe (CircularVector v a)
+fromList xs = fromListN (Prelude.length xs) xs
+{-# inline fromList #-}
+
+-- | Construct a 'CircularVector' from a list with a size hint.
+--
+--   since 0.1.2
+fromListN :: G.Vector v a => Int -> [a] -> Maybe (CircularVector v a)
+fromListN n xs = fromVector (G.fromListN n xs)
+{-# inline fromListN #-}
+
+-- | /O(n)/ Construct a 'CircularVector' from a list.
+--
+--   Calls @'error'@ if the input list is empty.
+--
+--   since 0.1.2
+unsafeFromList :: G.Vector v a => [a] -> CircularVector v a
+unsafeFromList xs = unsafeFromListN (Prelude.length xs) xs
+
+-- | /O(n)/ Construct a 'CircularVector' from a list with a size hint.
+--
+--   Calls @'error'@ if the input list is empty, or
+--   if the size hint is @'<=' 0@.
+--
+--    since 0.1.2
+unsafeFromListN :: G.Vector v a => Int -> [a] -> CircularVector v a
+unsafeFromListN n xs
+  | n <= 0 = error "Data.Vector.Circular.unsafeFromListN: invalid length!"
+  | otherwise = unsafeFromVector (G.fromListN n xs)
+
+-- | /O(1)/ Construct a singleton 'CircularVector.
+--
+--   since 0.1.2
+singleton :: G.Vector v a => a -> CircularVector v a
+singleton = unsafeFromVector . G.singleton
+{-# inline singleton #-}
+
+-- | /O(1)/ Index into a 'CircularVector'. This is always total.
+--
+--   since 0.1.2
+index :: G.Vector v a => CircularVector v a -> Int -> a
+index (CircularVector v r) = \ !ix ->
+  let len = G.length v
+  in G.unsafeIndex v (unsafeMod (ix + r) len)
+{-# inline index #-}
+
+-- | /O(1)/ Get the first element of a 'CircularVector'. This is always total.
+--
+--   since 0.1.2
+head :: G.Vector v a => CircularVector v a -> a
+head v = index v 0
+{-# inline head #-}
+
+-- | /O(1)/ Get the last element of a 'CircularVector'. This is always total.
+--
+--   since 0.1.2
+last :: G.Vector v a => CircularVector v a -> a
+last v = index v (Data.Vector.Circular.Generic.length v - 1)
+{-# inline last #-}
+
+-- | /O(1)/ Rotate the vector to left by @n@ number of elements.
+--
+--   /Note/: Right rotations start to break down due to
+--   arithmetic overflow when the size of the input vector is
+--   @'>' 'maxBound' @'Int'@
+--
+--   since 0.1.2
+rotateRight :: G.Vector v a => Int -> CircularVector v a -> CircularVector v a
+rotateRight r' (CircularVector v r) = CircularVector v h
+  where
+    len = G.length v
+    h = unsafeMod (r + unsafeMod r' len) len
+{-# inline rotateRight #-}
+
+-- | /O(1)/ Rotate the vector to the left by @n@ number of elements.
+--
+--   /Note/: Left rotations start to break down due to
+--   arithmetic underflow when the size of the input vector is
+--   @'>' 'maxBound' @'Int'@
+--
+--   since 0.1.2
+rotateLeft :: G.Vector v a => Int -> CircularVector v a -> CircularVector v a
+rotateLeft r' (CircularVector v r) = CircularVector v h
+  where
+    len = G.length v
+    h = unsafeMod (r - unsafeMod r' len) len
+{-# inline rotateLeft #-}
+{-
+-- | Construct a 'CircularVector' at compile-time using
+--   typed Template Haskell.
+--
+--   since 0.1.2
+vec :: (G.Vector v a, Lift a) => [a] -> Q (TExp (CircularVector v a))
+vec [] = fail "Cannot create an empty CircularVector!"
+vec xs =
+#if MIN_VERSION_template_haskell(2,16,0)
+  liftTyped (unsafeFromList xs)
+#else
+  unsafeTExpCoerce [|unsafeFromList xs|]
+#endif /* MIN_VERSION_template_haskell(2,16,0) */
+-}
+-- | since 0.1.2
+equivalent :: (G.Vector v a, Eq (v a), Ord a) => CircularVector v a -> CircularVector v a -> Bool
+equivalent x y = vector (canonise x) == vector (canonise y)
+
+-- | since 0.1.2
+canonise :: (G.Vector v a, Ord a) => CircularVector v a -> CircularVector v a
+canonise c@(CircularVector v r) = CircularVector v' (r - lr)
+  where
+    lr = leastRotation (toNonEmptyVector c)
+    v' = toVector (rotateRight lr (CircularVector v 0))
+
+-- | since 0.1.2
+leastRotation :: forall a. (Ord a) => NonEmptyVector a -> Int
+leastRotation v = runST go
+  where
+    go :: forall s. ST s Int
+    go = do
+      let s = v <> v
+      let len = NonEmpty.length s
+      f <- MVector.replicate @_ @Int len (-1)
+      kVar <- newMutVar @_ @Int 0
+      Control.Monad.forM_ [1..len-1] $ \j -> do
+        sj <- NonEmpty.indexM s j
+        i0 <- readMutVar kVar >>= \k -> MVector.read f (j - k - 1)
+        let loop i = do
+              a <- readMutVar kVar >>= \k -> NonEmpty.indexM s (k + i + 1)
+              if (i /= (-1) && sj /= a)
+                then do
+                  Control.Monad.when (sj < a) (writeMutVar kVar (j - i - 1))
+                  loop =<< MVector.read f i
+                else pure i
+        i <- loop i0
+        a <- readMutVar kVar >>= \k -> NonEmpty.indexM s (k + i + 1)
+        if sj /= a
+          then do
+            readMutVar kVar >>= \k -> Control.Monad.when (sj < (s NonEmpty.! k)) (writeMutVar kVar j)
+            readMutVar kVar >>= \k -> MVector.write f (j - k) (-1)
+          else do
+            readMutVar kVar >>= \k -> MVector.write f (j - k) (i + 1)
+      readMutVar kVar
+
+-- only safe if second argument is nonzero.
+-- used internally for modulus operations with length.
+unsafeMod :: Int -> Int -> Int
+unsafeMod = GHC.Base.modInt
+{-# inline unsafeMod #-}
+
+-- | /O(min(m,n))/ Zip two circular vectors with the given function.
+--
+--   @since 0.1.2
+zipWith :: (G.Vector v a, G.Vector v b, G.Vector v c) => (a -> b -> c) -> CircularVector v a -> CircularVector v b -> CircularVector v c
+zipWith f a b = unsafeFromVector $ G.zipWith f (toVector a) (toVector b)
+
+-- | Zip three circular vectors with the given function.
+--
+--   @since 0.1.2
+zipWith3 :: (G.Vector v a, G.Vector v b, G.Vector v c, G.Vector v d) => 
+  (a -> b -> c -> d) -> CircularVector v a -> CircularVector v b -> CircularVector v c
+  -> CircularVector v d
+zipWith3 f a b c = unsafeFromVector $ G.zipWith3 f (toVector a) (toVector b) (toVector c)
+
+-- | /O(min(n,m))/ Elementwise pairing of circular vector elements.
+--   This is a special case of 'zipWith' where the function argument is '(,)'
+--
+--   @since 0.1.2
+zip :: (G.Vector v a, G.Vector v b, G.Vector v (a,b)) => CircularVector v a -> CircularVector v b -> CircularVector v (a,b)
+zip a b = unsafeFromVector $ G.zip (toVector a) (toVector b)
+
+-- | Zip together three circular vectors.
+--
+--   @since 0.1.2
+zip3 :: (G.Vector v a, G.Vector v b, G.Vector v c, G.Vector v (a,b,c)) =>
+  CircularVector v a -> CircularVector v b -> CircularVector v c -> CircularVector v (a,b,c)
+zip3 a b c = unsafeFromVector $ G.zip3 (toVector a) (toVector b) (toVector c)
+
+-- | /O(n)/ Reverse a circular vector.
+--
+--   @since 0.1.2
+reverse :: G.Vector v a => CircularVector v a -> CircularVector v a
+reverse = unsafeFromVector . G.reverse . toVector
+
+-- | /O(n)/ Rotate to the minimum element of the circular vector according to the
+--   given comparison function.
+--
+--   @since 0.1.2
+rotateToMinimumBy :: G.Vector v a => (a -> a -> Ordering) -> CircularVector v a -> CircularVector v a
+rotateToMinimumBy f (CircularVector v _rot) =
+  CircularVector v (G.minIndexBy f v)
+
+-- | /O(n)/ Rotate to the maximum element of the circular vector according to the
+--   given comparison function.
+--
+--   @since 0.1.2
+rotateToMaximumBy :: G.Vector v a => (a -> a -> Ordering) -> CircularVector v a -> CircularVector v a
+rotateToMaximumBy f (CircularVector v _rot) =
+  CircularVector v (G.maxIndexBy f v)
+
+-- | /O(n)/ Check if all elements satisfy the predicate.
+--
+--   @since 0.1.2
+all :: G.Vector v a => (a -> Bool) -> CircularVector v a -> Bool
+all f = G.all f . vector
+
+-- | /O(n)/ Check if any element satisfies the predicate.
+--
+--   @since 0.1.2
+any :: G.Vector v a => (a -> Bool) -> CircularVector v a -> Bool
+any f = G.any f . vector
+
+-- | /O(n)/ Check if all elements are True.
+--
+--   @since 0.1.2
+and :: G.Vector v Bool => CircularVector v Bool -> Bool
+and = G.and . vector
+
+-- | /O(n)/ Check if any element is True.
+--
+--   @since 0.1.2
+or :: G.Vector v Bool => CircularVector v Bool -> Bool
+or = G.or . vector
+
+-- | /O(n)/ Compute the sum of the elements.
+--
+--   @since 0.1.2
+sum :: (G.Vector v a, Num a) => CircularVector v a -> a
+sum = G.sum . vector
+
+-- | /O(n)/ Compute the product of the elements.
+--
+--   @since 0.1.2
+product :: (G.Vector v a, Num a) => CircularVector v a -> a
+product = G.sum . vector
+
+-- | /O(n)/ Yield the maximum element of the circular vector.
+--
+--   @since 0.1.2
+maximum :: (G.Vector v a, Ord a) => CircularVector v a -> a
+maximum = G.maximum . vector
+
+-- | /O(n)/ Yield the maximum element of a circular vector according to the
+--   given comparison function.
+--
+--   @since 0.1.2
+maximumBy :: G.Vector v a => (a -> a -> Ordering) -> CircularVector v a -> a
+maximumBy f = G.maximumBy f . vector
+
+-- | /O(n)/ Yield the minimum element of the circular vector.
+--
+--   @since 0.1.2
+minimum :: (G.Vector v a, Ord a) => CircularVector v a -> a
+minimum = G.minimum . vector
+
+-- | /O(n)/ Yield the minimum element of a circular vector according to the
+--   given comparison function.
+--
+--   @since 0.1.2
+minimumBy :: G.Vector v a => (a -> a -> Ordering) -> CircularVector v a -> a
+minimumBy f = G.minimumBy f . vector
+
+-- | /O(n)/ Circular vector of the given length with the same value in
+-- each position.
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> replicate @Vector 3 "a"
+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})
+--
+-- >>> replicate @Vector 0 "a"
+-- Nothing
+--
+replicate :: G.Vector v a => Int -> a -> Maybe (CircularVector v a)
+replicate n a = fromVector (G.replicate n a)
+
+-- | /O(n)/ Circular vector of the given length with the same value in
+-- each position.
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> toList $ replicate1 @Vector 3 "a"
+-- ["a","a","a"]
+--
+-- >>> toList $ replicate1 @Vector 0 "a"
+-- ["a"]
+--
+-- >>> toList $ replicate1 @Vector (-1) "a"
+-- ["a"]
+replicate1 :: G.Vector v a => Int -> a -> CircularVector v a
+replicate1 n a = unsafeFromVector (G.replicate (max n 1) a)
+
+-- | /O(n)/ Construct a circular vector of the given length by applying the function to
+-- each index.
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> let f 0 = "a"; f _ = "k"; f :: Int -> String
+--
+-- >>> generate @Vector 1 f
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+-- >>> generate @Vector 0 f
+-- Nothing
+--
+-- >>> generate @Vector 2 f
+-- Just (CircularVector {vector = ["a","k"], rotation = 0})
+--
+generate :: G.Vector v a => Int -> (Int -> a) -> Maybe (CircularVector v a)
+generate n f = fromVector (G.generate n f)
+
+-- | /O(n)/ Construct a circular vector of the given length by applying the function to
+-- each index.
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> let f 0 = "a"; f _ = "k"; f :: Int -> String
+--
+-- >>> toList $ generate1 @Vector 2 f
+-- ["a","k"]
+--
+-- >>> toList $ generate1 @Vector 0 f
+-- ["a"]
+--
+-- >>> toList $ generate1 @Vector (-1) f
+-- ["a"]
+--
+generate1 :: G.Vector v a => Int -> (Int -> a) -> CircularVector v a
+generate1 n f = unsafeFromVector (G.generate (max n 1) f)
+
+-- | /O(n)/ Apply function n times to value. Zeroth element is original value.
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> iterateN @Vector 3 (+1) 0
+-- Just (CircularVector {vector = [0,1,2], rotation = 0})
+--
+-- >>> iterateN @Vector 0 (+1) 0
+-- Nothing
+--
+-- >>> iterateN @Vector (-1) (+1) 0
+-- Nothing
+--
+iterateN :: G.Vector v a => Int -> (a -> a) -> a -> Maybe (CircularVector v a)
+iterateN n f a = fromVector (G.iterateN n f a)
+
+-- | /O(n)/ Apply function n times to value. Zeroth element is original value.
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> iterateN1 @Vector 3 (+1) 0
+-- CircularVector {vector = [0,1,2], rotation = 0}
+--
+-- >>> iterateN1 @Vector 0 (+1) 0
+-- CircularVector {vector = [0], rotation = 0}
+--
+-- >>> iterateN1 @Vector (-1) (+1) 0
+-- CircularVector {vector = [0], rotation = 0}
+--
+iterateN1 :: G.Vector v a => Int -> (a -> a) -> a -> CircularVector v a
+iterateN1 n f a = unsafeFromVector (G.iterateN (max n 1) f a)
+
+-- | /O(n)/ Execute the monadic action the given number of times and store
+-- the results in a circular vector.
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> replicateM @Maybe @Vector 3 (Just "a")
+-- Just (Just (CircularVector {vector = ["a","a","a"], rotation = 0}))
+--
+-- >>> replicateM @Maybe @Vector 3 Nothing
+-- Nothing
+--
+-- >>> replicateM @Maybe @Vector 0 (Just "a")
+-- Just Nothing
+--
+-- >>> replicateM @Maybe @Vector (-1) (Just "a")
+-- Just Nothing
+--
+replicateM :: (Monad m, G.Vector v a) => Int -> m a -> m (Maybe (CircularVector v a))
+replicateM n a = fmap fromVector (G.replicateM n a)
+
+-- | /O(n)/ Execute the monadic action the given number of times and store
+-- the results in a circular vector.
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> replicate1M @Maybe @Vector 3 (Just "a")
+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})
+--
+-- >>> replicate1M @Maybe @Vector 3 Nothing
+-- Nothing
+--
+-- >>> replicate1M @Maybe @Vector 0 (Just "a")
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+-- >>> replicate1M @Maybe @Vector (-1) (Just "a")
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+replicate1M :: (Monad m, G.Vector v a) => Int -> m a -> m (CircularVector v a)
+replicate1M n a = fmap unsafeFromVector (G.replicateM (max n 1) a)
+
+-- | /O(n)/ Construct a circular vector of the given length by applying the monadic
+-- action to each index
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> generateM @[] @Vector 3 (\i -> if i < 1 then ["a"] else ["b"])
+-- [Just (CircularVector {vector = ["a","b","b"], rotation = 0})]
+--
+-- >>> generateM @[] @Vector @Int 3 (const [])
+-- []
+--
+-- >>> generateM @[] @Vector @Int 0 (const [1])
+-- [Nothing]
+--
+-- >>> generateM @Maybe @Vector @Int (-1) (const Nothing)
+-- Just Nothing
+--
+generateM :: (Monad m, G.Vector v a) => Int -> (Int -> m a) -> m (Maybe (CircularVector v a))
+generateM n f = fmap fromVector (G.generateM n f)
+
+-- | /O(n)/ Construct a circular vector of the given length by applying the monadic
+-- action to each index
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> generate1M @Maybe @Vector 3 (\i -> if i < 1 then Just "a" else Just "b")
+-- Just (CircularVector {vector = ["a","b","b"], rotation = 0})
+--
+-- >>> generate1M @[] @Vector 3 (const [])
+-- []
+--
+-- >>> generate1M @Maybe @Vector 0 (const $ Just 1)
+-- Just (CircularVector {vector = [1], rotation = 0})
+--
+-- >>> generate1M @Maybe @Vector (-1) (const Nothing)
+-- Nothing
+--
+generate1M :: (Monad m, G.Vector v a) => Int -> (Int -> m a) -> m (CircularVector v a)
+generate1M n f = fmap unsafeFromVector (G.generateM (max n 1) f)
+
+-- | /O(n)/ Apply monadic function n times to value. Zeroth element is
+-- original value.
+--
+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.
+--
+--   @since 0.1.2
+--
+-- >>> iterateNM @Maybe @Vector 3 return "a"
+-- Just (Just (CircularVector {vector = ["a","a","a"], rotation = 0}))
+--
+-- >>> iterateNM @Maybe @Vector 3 (const Nothing) "a"
+-- Nothing
+--
+-- >>> iterateNM @Maybe @Vector 0 return "a"
+-- Just Nothing
+--
+iterateNM :: (Monad m, G.Vector v a) => Int -> (a -> m a) -> a -> m (Maybe (CircularVector v a))
+iterateNM n f a = fmap fromVector (G.iterateNM n f a)
+
+-- | /O(n)/ Apply monadic function n times to value. Zeroth element is
+-- original value.
+--
+-- This variant takes @max n 1@ for the supplied length parameter.
+--
+--   @since 0.1.2
+--
+-- >>> iterateN1M @Maybe @Vector 3 return "a"
+-- Just (CircularVector {vector = ["a","a","a"], rotation = 0})
+--
+-- >>> iterateN1M @Maybe @Vector 3 (const Nothing) "a"
+-- Nothing
+--
+-- >>> iterateN1M @Maybe @Vector 0 return "a"
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+-- >>> iterateN1M @Maybe @Vector (-1) return "a"
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+iterateN1M :: (Monad m, G.Vector v a) => Int -> (a -> m a) -> a -> m (CircularVector v a)
+iterateN1M n f a = fmap unsafeFromVector (G.iterateNM (max n 1) f a)
+
+-- | Execute the monadic action and freeze the resulting circular vector.
+--
+--   @since 0.1.2
+create :: G.Vector v a => (forall s. ST s (G.Mutable v s a)) -> Maybe (CircularVector v a)
+create p = fromVector (G.create p)
+
+-- | Execute the monadic action and freeze the resulting circular vector,
+-- bypassing emptiness checks.
+--
+-- The onus is on the caller to guarantee the created vector is non-empty.
+--
+--   @since 0.1.2
+unsafeCreate :: G.Vector v a => (forall s. ST s (G.Mutable v s a)) -> CircularVector v a
+unsafeCreate p = unsafeFromVector (G.create p)
+
+-- | Execute the monadic action and freeze the resulting circular vector.
+--
+--   @since 0.1.2
+createT
+    :: (Traversable t, G.Vector v a)
+    => (forall s. ST s (t (G.Mutable v s a)))
+    -> t (Maybe (CircularVector v a))
+createT p = fmap fromVector (G.createT p)
+
+-- | Execute the monadic action and freeze the resulting circular vector.
+--
+-- The onus is on the caller to guarantee the created vector is non-empty.
+--
+--   @since 0.1.2
+unsafeCreateT
+    :: (Traversable t, G.Vector v a)
+    => (forall s. ST s (t (G.Mutable v s a)))
+    -> t (CircularVector v a)
+unsafeCreateT p = fmap unsafeFromVector (G.createT p)
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the
+-- generator function to a seed. The generator function yields 'Just' the
+-- next element and the new seed or 'Nothing' if there are no more
+-- elements.
+--
+-- If an unfold does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+--
+-- >>> unfoldr @Vector (\b -> case b of "a" -> Just ("a", "b"); _ ->  Nothing) "a"
+-- Just (CircularVector {vector = ["a"], rotation = 0})
+--
+-- >>> unfoldr @Vector (const Nothing) "a"
+-- Nothing
+--
+unfoldr :: G.Vector v a => (b -> Maybe (a, b)) -> b -> Maybe (CircularVector v a)
+unfoldr f b = fromVector (G.unfoldr f b)
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the
+-- generator function to a seed and a first element.
+--
+-- This variant of 'unfoldr' guarantees the resulting vector is non-
+-- empty by supplying an initial element @a@.
+--
+--   @since 0.1.2
+--
+-- >>> unfoldr1 @Vector (\b -> case b of "a" -> Just ("a", "b"); _ ->  Nothing) "first" "a"
+-- CircularVector {vector = ["first","a"], rotation = 0}
+--
+-- >>> unfoldr1 @Vector (const Nothing) "first" "a"
+-- CircularVector {vector = ["first"], rotation = 0}
+--
+unfoldr1 :: G.Vector v a => (b -> Maybe (a, b)) -> a -> b -> CircularVector v a
+unfoldr1 f a b = cons a (unsafeFromVector (G.unfoldr f b))
+
+-- | /O(n)/ Construct a circular vector with at most n elements by repeatedly
+-- applying the generator function to a seed. The generator function yields
+-- 'Just' the next element and the new seed or 'Nothing' if there are no
+-- more elements.
+--
+-- If an unfold does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+--
+-- >>> unfoldrN @Vector 3 (\b -> Just (b+1, b+1)) 0
+-- Just (CircularVector {vector = [1,2,3], rotation = 0})
+--
+-- >>> unfoldrN @Vector 3 (const Nothing) 0
+-- Nothing
+--
+-- >>> unfoldrN @Vector 0 (\b -> Just (b+1, b+1)) 0
+-- Nothing
+--
+unfoldrN :: G.Vector v a => Int -> (b -> Maybe (a, b)) -> b -> Maybe (CircularVector v a)
+unfoldrN n f b = fromVector (G.unfoldrN n f b)
+
+-- | /O(n)/ Construct a circular vector with at most n elements by repeatedly
+-- applying the generator function to a seed. The generator function yields
+-- 'Just' the next element and the new seed or 'Nothing' if there are no
+-- more elements.
+--
+-- This variant of 'unfoldrN' guarantees the resulting vector is non-
+-- empty by supplying an initial element @a@.
+--
+--   @since 0.1.2
+--
+-- >>> unfoldr1N @Vector 3 (\b -> Just (b+1, b+1)) 0 0
+-- CircularVector {vector = [0,1,2,3], rotation = 0}
+--
+-- >>> unfoldr1N @Vector 3 (const Nothing) 0 0
+-- CircularVector {vector = [0], rotation = 0}
+--
+-- >>> unfoldr1N @Vector 0 (\b -> Just (b+1, b+1)) 0 0
+-- CircularVector {vector = [0], rotation = 0}
+--
+unfoldr1N
+    :: G.Vector v a
+    => Int
+    -> (b -> Maybe (a, b))
+    -> a
+    -> b
+    -> CircularVector v a
+unfoldr1N n f a b = cons a (unsafeFromVector (G.unfoldrN n f b))
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator
+-- function to a seed. The generator function yields Just the next element
+-- and the new seed or Nothing if there are no more elements.
+--
+-- If an unfold does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+unfoldrM
+    :: (Monad m, G.Vector v a)
+    => (b -> m (Maybe (a, b)))
+    -> b
+    -> m (Maybe (CircularVector v a))
+unfoldrM f b = fmap fromVector (G.unfoldrM f b)
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator
+-- function to a seed. The generator function yields Just the next element
+-- and the new seed or Nothing if there are no more elements.
+--
+-- This variant of 'unfoldrM' guarantees the resulting vector is non-
+-- empty by supplying an initial element @a@.
+--
+--   @since 0.1.2
+unfoldr1M
+    :: (Monad m, G.Vector v a)
+    => (b -> m (Maybe (a, b)))
+    -> a
+    -> b
+    -> m (CircularVector v a)
+unfoldr1M f a b = fmap (cons a . unsafeFromVector) (G.unfoldrM f b)
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator
+-- function to a seed. The generator function yields Just the next element and
+-- the new seed or Nothing if there are no more elements.
+--
+-- If an unfold does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+unfoldrNM
+    :: (Monad m, G.Vector v a)
+    => Int
+    -> (b -> m (Maybe (a, b)))
+    -> b
+    -> m (Maybe (CircularVector v a))
+unfoldrNM n f b = fmap fromVector (G.unfoldrNM n f b)
+
+-- | /O(n)/ Construct a circular vector by repeatedly applying the monadic generator
+-- function to a seed. The generator function yields Just the next element and
+-- the new seed or Nothing if there are no more elements.
+--
+-- This variant of 'unfoldrNM' guarantees the resulting vector is non-
+-- empty by supplying an initial element @a@.
+--
+--   @since 0.1.2
+unfoldr1NM
+    :: (Monad m, G.Vector v a)
+    => Int
+    -> (b -> m (Maybe (a, b)))
+    -> a
+    -> b
+    -> m (CircularVector v a)
+unfoldr1NM n f a b = fmap (cons a . unsafeFromVector) (G.unfoldrNM n f b)
+
+-- | /O(n)/ Construct a circular vector with n elements by repeatedly applying the
+-- generator function to the already constructed part of the vector.
+--
+-- If 'constructN' does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+constructN :: G.Vector v a => Int -> (v a -> a) -> Maybe (CircularVector v a)
+constructN n f = fromVector (G.constructN n f)
+
+-- | /O(n)/ Construct a circular vector with n elements from right to left by repeatedly
+-- applying the generator function to the already constructed part of the vector.
+--
+-- If 'constructrN' does not create meaningful values, 'Nothing' is
+-- returned. Otherwise, 'Just' containing a circular vector is returned.
+--
+--   @since 0.1.2
+constructrN :: G.Vector v a => Int -> (v a -> a) -> Maybe (CircularVector v a)
+constructrN n f = fromVector (G.constructrN n f)
+
+-- | /O(n)/ Yield a circular vector of the given length containing the
+-- values x, x+1 etc. This operation is usually more efficient than
+-- 'enumFromTo'.
+--
+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,
+-- otherwise, 'Just' containing a circular vector.
+--
+--   @since 0.1.2
+enumFromN :: (G.Vector v a, Num a) => a -> Int -> Maybe (CircularVector v a)
+enumFromN a n = fromVector (G.enumFromN a n)
+
+-- | /O(n)/ Yield a circular vector of length @max n 1@ containing the
+-- values x, x+1 etc. This operation is usually more efficient than
+-- 'enumFromTo'.
+--
+--   @since 0.1.2
+enumFromN1 :: (G.Vector v a, Num a) => a -> Int -> CircularVector v a
+enumFromN1 a n = unsafeFromVector (G.enumFromN a (max n 1))
+
+-- | /O(n)/ Yield a circular vector of the given length containing the
+-- values x, x+y, x+y+y etc. This operations is usually more efficient than
+-- 'enumFromThenTo'.
+--
+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,
+-- otherwise, 'Just' containing a circular vector.
+--
+--   @since 0.1.2
+enumFromStepN :: (G.Vector v a, Num a) => a -> a -> Int -> Maybe (CircularVector v a)
+enumFromStepN a0 a1 n = fromVector (G.enumFromStepN a0 a1 n)
+
+-- | /O(n)/ Yield a circular vector of length @max n 1@ containing the
+-- values x, x+y, x+y+y etc. This operations is usually more efficient than
+-- 'enumFromThenTo'.
+--
+--   @since 0.1.2
+enumFromStepN1 :: (G.Vector v a, Num a) => a -> a -> Int -> CircularVector v a
+enumFromStepN1 a0 a1 n = unsafeFromVector (G.enumFromStepN a0 a1 (max n 1))
+
+-- | /O(n)/ Enumerate values from x to y.
+--
+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,
+-- otherwise, 'Just' containing a circular vector.
+--
+-- /WARNING/: This operation can be very inefficient. If at all possible,
+-- use 'enumFromN' instead.
+--
+--
+--   @since 0.1.2
+enumFromTo :: (G.Vector v a, Enum a) => a -> a -> Maybe (CircularVector v a)
+enumFromTo a0 a1 = fromVector (G.enumFromTo a0 a1)
+
+-- | /O(n)/ Enumerate values from x to y with a specific step z.
+--
+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,
+-- otherwise, 'Just' containing a circular vector.
+--
+-- /WARNING/: This operation can be very inefficient. If at all possible,
+-- use 'enumFromStepN' instead.
+--
+--   @since 0.1.2
+enumFromThenTo :: (G.Vector v a, Enum a) => a -> a -> a -> Maybe (CircularVector v a)
+enumFromThenTo a0 a1 a2 = fromVector (G.enumFromThenTo a0 a1 a2)
+
+-- | /O(n)/ Prepend an element
+--
+--   @since 0.1.2
+--
+-- >>> cons 1 (unsafeFromList @Vector [2,3])
+-- CircularVector {vector = [1,2,3], rotation = 0}
+--
+cons :: G.Vector v a => a -> CircularVector v a -> CircularVector v a
+cons a cv = consV a (toVector cv)
+{-# INLINE cons #-}
+
+-- | /O(n)/ Prepend an element to a Vector
+--
+--   @since 0.1.2
+--
+-- >>> consV 1 (Data.Vector.fromList [2,3])
+-- CircularVector {vector = [1,2,3], rotation = 0}
+--
+consV :: G.Vector v a => a -> v a -> CircularVector v a
+consV a = unsafeFromVector . G.cons a
+{-# INLINE consV #-}
+
+-- | /O(n)/ Append an element
+--
+--   @since 0.1.2
+--
+-- >>> snoc (unsafeFromList @Vector [1,2]) 3
+-- CircularVector {vector = [1,2,3], rotation = 0}
+--
+snoc :: G.Vector v a => CircularVector v a -> a -> CircularVector v a
+snoc = snocV . toVector
+
+-- | /O(n)/ Append an element to a Vector
+--
+--   @since 0.1.2
+--
+-- >>> snocV (Data.Vector.fromList [1,2]) 3
+-- CircularVector {vector = [1,2,3], rotation = 0}
+--
+snocV :: G.Vector v a => v a -> a -> CircularVector v a
+snocV as = unsafeFromVector . G.snoc as
+
+-- | /O(m+n)/ Concatenate two circular vectors
+--
+--   @since 0.1.2
+--
+-- >>> (unsafeFromList @Vector [1..3]) ++ (unsafeFromList [4..6])
+-- CircularVector {vector = [1,2,3,4,5,6], rotation = 0}
+--
+(++) :: G.Vector v a => CircularVector v a -> CircularVector v a -> CircularVector v a
+v ++ v' = unsafeFromVector (toVector v G.++ toVector v')
+
+-- | /O(n)/ Concatenate all circular vectors in the list
+--
+-- If list is empty, 'Nothing' is returned, otherwise 'Just'
+-- containing the concatenated circular vectors
+--
+--   @since 0.1.2
+--
+-- >>> concat [(unsafeFromList @Vector [1..3]), (unsafeFromList [4..6])]
+-- Just (CircularVector {vector = [1,2,3,4,5,6], rotation = 0})
+--
+concat :: G.Vector v a => [CircularVector v a] -> Maybe (CircularVector v a)
+concat [] = Nothing
+concat (a:as) = Just (concat1 (a :| as))
+{-# INLINE concat #-}
+
+-- | O(n) Concatenate all circular vectors in a non-empty list.
+--
+--   @since 0.1.2
+--
+-- >>> concat1 ((unsafeFromList @Vector [1..3]) :| [(unsafeFromList [4..6])])
+-- CircularVector {vector = [1,2,3,4,5,6], rotation = 0}
+--
+concat1 :: G.Vector v a => NonEmpty (CircularVector v a) -> CircularVector v a
+concat1 = unsafeFromVector . G.concatNE . fmap toVector
+
+-- | /O(n)/ Map a function over a circular vector.
+--
+--   @since 0.1.2
+--
+-- >>> map (+1) $ unsafeFromList @Vector [1..3]
+-- CircularVector {vector = [2,3,4], rotation = 0}
+--
+map :: (G.Vector v a, G.Vector v b) => (a -> b) -> CircularVector v a -> CircularVector v b
+map f (CircularVector v rot) = CircularVector (G.map f v) rot
+
+-- | /O(n)/ Apply a function to every element of a circular vector and
+-- its index.
+--
+--   @since 0.1.2
+--
+-- >>> imap (\i a -> if i == 2 then a+1 else a+0) $ unsafeFromList @Vector [1..3]
+-- CircularVector {vector = [1,2,4], rotation = 0}
+--
+imap :: (G.Vector v a, G.Vector v b) => (Int -> a -> b) -> CircularVector v a -> CircularVector v b
+imap f = unsafeFromVector . G.imap f . toVector
+
+-- | Map a function over a circular vector and concatenate the results.
+--
+--   @since 0.1.2
+--
+-- >>> concatMap (\a -> unsafeFromList @Vector [a,a]) (unsafeFromList [1,2,3])
+-- CircularVector {vector = [1,1,2,2,3,3], rotation = 0}
+--
+concatMap
+    :: (G.Vector v a, G.Vector v b)
+    => (a -> CircularVector v b)
+    -> CircularVector v a
+    -> CircularVector v b
+concatMap f = unsafeFromVector . G.concatMap (toVector . f) . toVector
+
+-- | /O(n)/ Apply the monadic action to all elements of the circular
+-- vector, yielding circular vector of results.
+--
+--   @since 0.1.2
+--
+-- >>> mapM Just (unsafeFromList @Vector [1..3])
+-- Just (CircularVector {vector = [1,2,3], rotation = 0})
+--
+-- >>> mapM (const Nothing) (unsafeFromList @Vector [1..3])
+-- Nothing
+--
+mapM :: (Monad m, G.Vector v a, G.Vector v b) => (a -> m b) -> CircularVector v a -> m (CircularVector v b)
+mapM f = fmap unsafeFromVector . G.mapM f . toVector
+
+-- | /O(n)/ Apply the monadic action to every element of a circular
+-- vector and its index, yielding a circular vector of results.
+--
+--   @since 0.1.2
+--
+-- >>> imapM (\i a -> if i == 1 then Just a else Just 0) (unsafeFromList @Vector [1..3])
+-- Just (CircularVector {vector = [0,2,0], rotation = 0})
+--
+-- >>> imapM (\_ _ -> Nothing) (unsafeFromList @Vector [1..3])
+-- Nothing
+--
+imapM
+    :: (Monad m, G.Vector v a, G.Vector v b)
+    => (Int -> a -> m b)
+    -> CircularVector v a
+    -> m (CircularVector v b)
+imapM f = fmap unsafeFromVector . G.imapM f . toVector
+
+-- | /O(n)/ Apply the monadic action to all elements of a circular vector
+-- and ignore the results.
+--
+--   @since 0.1.2
+--
+-- >>> mapM_ (const $ Just ()) (unsafeFromList @Vector [1..3])
+-- Just ()
+--
+-- >>> mapM_ (const Nothing) (unsafeFromList @Vector [1..3])
+-- Nothing
+--
+mapM_ :: (Monad m, G.Vector v a, G.Vector v b) => (a -> m b) -> CircularVector v a -> m ()
+mapM_ f = G.mapM_ f . toVector
+
+-- | /O(n)/ Apply the monadic action to every element of a circular
+-- vector and its index, ignoring the results
+--
+--   @since 0.1.2
+--
+-- >>> imapM_ (\i a -> if i == 1 then print a else putStrLn "0") (unsafeFromList @Vector [1..3])
+-- 0
+-- 2
+-- 0
+--
+-- >>> imapM_ (\_ _ -> Nothing) (unsafeFromList @Vector [1..3])
+-- Nothing
+--
+imapM_ :: (Monad m, G.Vector v a) => (Int -> a -> m b) -> CircularVector v a -> m ()
+imapM_ f = G.imapM_ f . toVector
+
+-- | /O(n)/ Apply the monadic action to all elements of the circular
+-- vector, yielding a circular vector of results.
+--
+-- Equivalent to @flip 'mapM'@.
+--
+--   @since 0.1.2
+forM :: (Monad m, G.Vector v a, G.Vector v b) => CircularVector v a -> (a -> m b) -> m (CircularVector v b)
+forM cv f = unsafeFromVector <$> G.forM (toVector cv) f
+
+-- | /O(n)/ Apply the monadic action to all elements of a circular
+-- vector and ignore the results.
+--
+-- Equivalent to @flip 'mapM_'@.
+--
+--   @since 0.1.2
+forM_ :: (Monad m, G.Vector v a) => CircularVector v a -> (a -> m b) -> m ()
+forM_ cv f = G.forM_ (toVector cv) f
+
+-- | /O(n)/ Drop repeated adjacent elements.
+--
+-- >>> toList $ uniq $ unsafeFromList @Vector [1,1,2,2,3,3,1]
+-- [1,2,3]
+--
+-- >>> toList $ uniq $ unsafeFromList @Vector [1,2,3,1]
+-- [1,2,3]
+uniq :: (G.Vector v a, Eq a) => CircularVector v a -> CircularVector v a
+uniq = unsafeFromVector . trim . G.uniq . toVector
+  where
+    trim v
+      | G.length v == 1 || G.head v /= G.last v
+        = v
+      | otherwise
+        = trim (G.unsafeInit v)
+
+-- | /O(n)/ Drop elements when predicate returns Nothing
+--
+-- If no elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> mapMaybe (\a -> if a == 2 then Nothing else Just a) (unsafeFromList @Vector [1..3])
+-- [1,3]
+mapMaybe
+    :: (G.Vector v a, G.Vector v b)
+    => (a -> Maybe b)
+    -> CircularVector v a
+    -> v b
+mapMaybe f = G.mapMaybe f . toVector
+
+-- | /O(n)/ Drop elements when predicate, applied to index and value, returns Nothing
+--
+-- If no elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> imapMaybe (\i a -> if a == 2 || i == 2 then Nothing else Just a) (unsafeFromList @Vector [1..3])
+-- [1]
+--
+imapMaybe
+    :: (G.Vector v a, G.Vector v b)
+    => (Int -> a -> Maybe b)
+    -> CircularVector v a
+    -> v b
+imapMaybe f = G.imapMaybe f . toVector
+
+-- | /O(n)/ Yield the longest prefix of elements satisfying the predicate
+-- without copying.
+--
+-- If no elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> takeWhile (/= 3) (unsafeFromList @Vector [1..3])
+-- [1,2]
+--
+takeWhile :: G.Vector v a => (a -> Bool) -> CircularVector v a -> v a
+takeWhile f = G.takeWhile f . toVector
+
+-- | /O(n)/ Drop the longest prefix of elements that satisfy the predicate
+-- without copying.
+--
+-- If all elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> dropWhile (/= 3) (unsafeFromList @Vector [1..3])
+-- [3]
+--
+dropWhile :: G.Vector v a => (a -> Bool) -> CircularVector v a -> v a
+dropWhile f = G.dropWhile f . toVector
+
+-- | /O(n)/ Split the circular vector in two parts, the first one
+-- containing those elements that satisfy the predicate and the second
+-- one those that don't. The relative order of the elements is preserved
+-- at the cost of a sometimes reduced performance compared to
+-- 'unstablePartition'.
+--
+-- If all or no elements satisfy the predicate, one of the resulting vectors
+-- may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> partition (< 3) (unsafeFromList @Vector [1..5])
+-- ([1,2],[3,4,5])
+--
+partition :: G.Vector v a => (a -> Bool) -> CircularVector v a -> (v a, v a)
+partition f = G.partition f . toVector
+
+-- | /O(n)/ Split the circular vector in two parts, the first one
+-- containing those elements that satisfy the predicate and the second
+-- one those that don't. The order of the elements is not preserved but
+-- the operation is often faster than 'partition'.
+--
+-- If all or no elements satisfy the predicate, one of the resulting vectors
+-- may be empty.
+--
+--   @since 0.1.2
+unstablePartition
+    :: G.Vector v a
+    => (a -> Bool)
+    -> CircularVector v a
+    -> (v a, v a)
+unstablePartition f = G.unstablePartition f . toVector
+
+-- | /O(n)/ Split the circular vector into the longest prefix of elements
+-- that satisfy the predicate and the rest without copying.
+--
+-- If all or no elements satisfy the predicate, one of the resulting vectors
+-- may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> span (== 1) (unsafeFromList @Vector [1,1,2,3,1])
+-- ([1,1],[2,3,1])
+--
+span :: G.Vector v a => (a -> Bool) -> CircularVector v a -> (v a, v a)
+span f = G.span f . toVector
+
+-- | /O(n)/ Split the circular vector into the longest prefix of elements that do not
+-- satisfy the predicate and the rest without copying.
+--
+-- If all or no elements satisfy the predicate, one of the resulting vectors
+-- may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> break (== 2) (unsafeFromList @Vector [1,1,2,3,1])
+-- ([1,1],[2,3,1])
+--
+break :: G.Vector v a => (a -> Bool) -> CircularVector v a -> (v a, v a)
+break f = G.break f . toVector
+
+-- | /O(n)/ Check if the circular vector contains an element
+--
+--   @since 0.1.2
+--
+-- >>> elem 1 $ unsafeFromList @Vector [1..3]
+-- True
+-- >>> elem 4 $ unsafeFromList @Vector [1..3]
+-- False
+--
+elem :: (G.Vector v a, Eq a) => a -> CircularVector v a -> Bool
+elem a = G.elem a . toVector
+
+-- | /O(n)/ Check if the circular vector does not contain an element
+-- (inverse of 'elem')
+--
+--   @since 0.1.2
+--
+-- >>> notElem 1 $ unsafeFromList @Vector [1..3]
+-- False
+--
+-- >>> notElem 4 $ unsafeFromList @Vector [1..3]
+-- True
+--
+notElem :: (G.Vector v a, Eq a) => a -> CircularVector v a -> Bool
+notElem a = G.notElem a . toVector
+
+-- | /O(n)/ Yield 'Just' the first element matching the predicate or
+-- 'Nothing' if no such element exists.
+--
+--   @since 0.1.2
+--
+-- >>> find (< 2) $ unsafeFromList @Vector [1..3]
+-- Just 1
+--
+-- >>> find (< 0) $ unsafeFromList @Vector [1..3]
+-- Nothing
+--
+find :: G.Vector v a => (a -> Bool) -> CircularVector v a -> Maybe a
+find f = G.find f . toVector
+
+-- | /O(n)/ Yield 'Just' the index of the first element matching the
+-- predicate or 'Nothing' if no such element exists.
+--
+--   @since 0.1.2
+--
+-- >>> findIndex (< 2) $ unsafeFromList @Vector [1..3]
+-- Just 0
+--
+-- >>> findIndex (< 0) $ unsafeFromList @Vector [1..3]
+-- Nothing
+--
+-- >>> findIndex (==1) $ rotateRight 1 (unsafeFromList @Vector [1..3])
+-- Just 2
+findIndex :: G.Vector v a => (a -> Bool) -> CircularVector v a -> Maybe Int
+findIndex f = G.findIndex f . toVector
+
+-- | /O(n)/ Yield the indices of elements satisfying the predicate in
+-- ascending order.
+--
+--   @since 0.1.2
+--
+-- >>> findIndices (< 3) $ unsafeFromList @Vector [1..3]
+-- [0,1]
+--
+-- >>> findIndices (< 0) $ unsafeFromList @Vector [1..3]
+-- []
+--
+findIndices :: (G.Vector v a, G.Vector v Int) => (a -> Bool) -> CircularVector v a -> v Int
+findIndices f = G.findIndices f . toVector
+
+-- | /O(n)/ Yield 'Just' the index of the first occurence of the given
+-- element or 'Nothing' if the circular vector does not contain the
+-- element. This is a specialised version of 'findIndex'.
+--
+--   @since 0.1.2
+--
+-- >>> elemIndex 1 $ unsafeFromList @Vector [1..3]
+-- Just 0
+--
+-- >>> elemIndex 0 $ unsafeFromList @Vector [1..3]
+-- Nothing
+--
+elemIndex :: (G.Vector v a, Eq a) => a -> CircularVector v a -> Maybe Int
+elemIndex a = G.elemIndex a . toVector
+
+-- | /O(n)/ Yield the indices of all occurences of the given element in
+-- ascending order. This is a specialised version of 'findIndices'.
+--
+--   @since 0.1.2
+--
+-- >>> elemIndices 1 $ unsafeFromList @Vector [1,2,3,1]
+-- [0,3]
+--
+-- >>> elemIndices 0 $ unsafeFromList @Vector [1..3]
+-- []
+--
+elemIndices :: (G.Vector v a, G.Vector v Int, Eq a) => a -> CircularVector v a -> v Int
+elemIndices a = G.elemIndices a . toVector
+
+-- | /O(n)/ Drop elements that do not satisfy the predicate which is
+-- applied to values and their indices.
+--
+-- If no elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> ifilter (\i a -> if a == 2 || i == 0 then False else True) (unsafeFromList @Vector [1..3])
+-- [3]
+--
+-- >>> ifilter (\_ _ -> False) (unsafeFromList @Vector [1..3])
+-- []
+--
+ifilter
+    :: G.Vector v a
+    => (Int -> a -> Bool)
+    -> CircularVector v a
+    -> v a
+ifilter f = G.ifilter f . toVector
+
+-- | /O(n)/ Drop elements that do not satisfy the monadic predicate.
+--
+-- If no elements satisfy the predicate, the resulting vector may be empty.
+--
+--   @since 0.1.2
+--
+-- >>> filterM (\a -> if a == 2 then Just False else Just True) (unsafeFromList @Vector [1..3])
+-- Just [1,3]
+--
+-- >>> filterM (\a -> if a == 2 then Nothing else Just True) (unsafeFromList @Vector [1..3])
+-- Nothing
+--
+-- >>> filterM (const $ Just False) (unsafeFromList @Vector [1..3])
+-- Just []
+--
+filterM
+    :: (Monad m, G.Vector v a)
+    => (a -> m Bool)
+    -> CircularVector v a
+    -> m (v a)
+filterM f = G.filterM f . toVector
+
+-- -- | /O(n)/ Drop elements that do not satisfy the monadic predicate that is
+-- -- a function of index and value.
+-- --
+-- -- If no elements satisfy the predicate, the resulting vector may be empty.
+-- --
+-- --   @since 0.1.2
+-- --
+-- -- >>> ifilterM (\i a -> if a == 2 || i == 0 then Just False else Just True) (unsafeFromList @Vector [1..3])
+-- -- Just [3]
+-- --
+-- -- >>> ifilterM (\i a -> if a == 2 || i == 0 then Nothing else Just True) (unsafeFromList @Vector [1..3])
+-- -- Nothing
+-- --
+-- -- >>> ifilterM (\_ _ -> Just False) (unsafeFromList @Vector [1..3])
+-- -- Just []
+-- --
+-- ifilterM
+--     :: (Monad m, G.Vector v a)
+--     => (Int -> a -> m Bool)
+--     -> CircularVector v a
+--     -> m (Vector a)
+-- ifilterM f = G.ifilterM f . toVector
+
+-- | /O(n)/ Yield the circular vector obtained by replacing each element
+-- @i@ of the circular index vector by @xs'!'i@. This is equivalent to
+-- @'map' (xs'!') is@ but is often much more efficient.
+--
+--   @since 0.1.2
+--
+-- >>> toList $ backpermute @Vector (unsafeFromList @Vector [1..3]) (unsafeFromList @Vector [2,0])
+-- [3,1]
+--
+backpermute :: (G.Vector v a, G.Vector v Int) =>
+  CircularVector v a -> CircularVector v Int -> CircularVector v a
+backpermute v i = unsafeFromVector $ G.backpermute (toVector v) (toVector i)
+
+-- | Same as 'backpermute' but without bounds checking.
+--
+--   @since 0.1.2
+unsafeBackpermute
+    :: (G.Vector v a, G.Vector v Int)
+    => CircularVector v a
+    -> CircularVector v Int
+    -> CircularVector v a
+unsafeBackpermute v i = unsafeFromVector (G.unsafeBackpermute (toVector v) (toVector i))
+
+-- | Apply a destructive operation to a circular vector. The operation
+-- will be performed in place if it is safe to do so and will modify a
+-- copy of the circular vector otherwise.
+--
+--   @since 0.1.2
+modify
+    :: G.Vector v a
+    => (forall s. G.Mutable v s a -> ST s ())
+    -> CircularVector v a
+    -> CircularVector v a
+modify p = unsafeFromVector . G.modify p . toVector
diff --git a/test/doctests.hs b/test/doctests.hs
new file mode 100644
--- /dev/null
+++ b/test/doctests.hs
@@ -0,0 +1,34 @@
+module Main (main) where
+
+import Test.DocTest
+
+
+main :: IO ()
+main = doctest $ ["-isrc" ] ++ ghcExts ++ files
+
+
+ghcExts :: [String]
+ghcExts = map ("-X" ++)
+          [ "Haskell2010"
+          , "TypeApplications"
+          ]
+
+files :: [String]
+files = map toFile modules
+
+
+toFile :: String -> String
+toFile = (\s -> "src/" <> s <> ".hs") . replace '.' '/'
+
+replace     :: Eq a => a -> a -> [a] -> [a]
+replace a b = go
+  where
+    go []                 = []
+    go (c:cs) | c == a    = b:go cs
+              | otherwise = c:go cs
+
+modules :: [String]
+modules =
+  [ "Data.Vector.Circular"
+  , "Data.Vector.Circular.Generic"
+  ]
diff --git a/vector-circular.cabal b/vector-circular.cabal
--- a/vector-circular.cabal
+++ b/vector-circular.cabal
@@ -2,7 +2,7 @@
 name:
   vector-circular
 version:
-  0.1.1
+  0.1.2
 synopsis:
   circular vectors
 description:
@@ -30,6 +30,7 @@
     src
   exposed-modules:
     Data.Vector.Circular
+    Data.Vector.Circular.Generic
   build-depends:
     , base >= 4.11 && < 4.17
     , nonempty-vector >= 0.2 && < 0.3
@@ -58,6 +59,19 @@
     , hedgehog-classes
   default-language:
     Haskell2010
+
+test-suite doctests
+  if os(windows)
+    buildable:    False
+  type:           exitcode-stdio-1.0
+  ghc-options:    -threaded
+  hs-source-dirs: test
+  main-is:        doctests.hs
+  build-depends:  base
+                , doctest             >= 0.8
+
+  default-language:    Haskell2010
+
 
 source-repository head
   type:
