nonempty-vector 0.3 → 1.0
raw patch · 20 files changed
+5960/−23 lines, 20 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Vector.NonEmpty.Unboxed: (!) :: Unbox a => NonEmptyUVector a -> Int -> a
+ Data.Vector.NonEmpty.Unboxed: (!?) :: Unbox a => NonEmptyUVector a -> Int -> Maybe a
+ Data.Vector.NonEmpty.Unboxed: (++) :: Unbox a => NonEmptyUVector a -> NonEmptyUVector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: (//) :: Unbox a => NonEmptyUVector a -> [(Int, a)] -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: accum :: (Unbox a, Unbox b) => (a -> b -> a) -> NonEmptyUVector a -> [(Int, b)] -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: accumulate :: (Unbox a, Unbox b) => (a -> b -> a) -> NonEmptyUVector a -> Vector (Int, b) -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: accumulate_ :: (Unbox a, Unbox b) => (a -> b -> a) -> NonEmptyUVector a -> Vector Int -> Vector b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: all :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> Bool
+ Data.Vector.NonEmpty.Unboxed: and :: NonEmptyUVector Bool -> Bool
+ Data.Vector.NonEmpty.Unboxed: any :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> Bool
+ Data.Vector.NonEmpty.Unboxed: backpermute :: Unbox a => NonEmptyUVector a -> NonEmptyUVector Int -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: break :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> (Vector a, Vector a)
+ Data.Vector.NonEmpty.Unboxed: concat :: Unbox a => [NonEmptyUVector a] -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: concat1 :: Unbox a => NonEmpty (NonEmptyUVector a) -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: concatMap :: (Unbox a, Unbox b) => (a -> NonEmptyUVector b) -> NonEmptyUVector a -> NonEmptyUVector b
+ Data.Vector.NonEmpty.Unboxed: cons :: Unbox a => a -> NonEmptyUVector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: consV :: Unbox a => a -> Vector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: constructN :: Unbox a => Int -> (Vector a -> a) -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: constructrN :: Unbox a => Int -> (Vector a -> a) -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: create :: Unbox a => (forall s. () => ST s (MVector s a)) -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: createT :: (Traversable t, Unbox a) => (forall s. () => ST s (t (MVector s a))) -> t (Maybe (NonEmptyUVector a))
+ Data.Vector.NonEmpty.Unboxed: data NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: drop :: Unbox a => Int -> NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: dropWhile :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: elem :: (Unbox a, Eq a) => a -> NonEmptyUVector a -> Bool
+ Data.Vector.NonEmpty.Unboxed: elemIndex :: (Unbox a, Eq a) => a -> NonEmptyUVector a -> Maybe Int
+ Data.Vector.NonEmpty.Unboxed: elemIndices :: (Unbox a, Eq a) => a -> NonEmptyUVector a -> Vector Int
+ Data.Vector.NonEmpty.Unboxed: enumFromN :: (Unbox a, Num a) => a -> Int -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: enumFromN1 :: (Unbox a, Num a) => a -> Int -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: enumFromStepN :: (Unbox a, Num a) => a -> a -> Int -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: enumFromStepN1 :: (Unbox a, Num a) => a -> a -> Int -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: enumFromThenTo :: (Unbox a, Enum a) => a -> a -> a -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: enumFromTo :: (Unbox a, Enum a) => a -> a -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: filter :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: filterM :: (Unbox a, Monad m) => (a -> m Bool) -> NonEmptyUVector a -> m (Vector a)
+ Data.Vector.NonEmpty.Unboxed: find :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> Maybe a
+ Data.Vector.NonEmpty.Unboxed: findIndex :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> Maybe Int
+ Data.Vector.NonEmpty.Unboxed: findIndices :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> Vector Int
+ Data.Vector.NonEmpty.Unboxed: fold1M :: (Unbox a, Monad m) => (a -> a -> m a) -> NonEmptyUVector a -> m a
+ Data.Vector.NonEmpty.Unboxed: fold1M' :: (Unbox a, Monad m) => (a -> a -> m a) -> NonEmptyUVector a -> m a
+ Data.Vector.NonEmpty.Unboxed: fold1M'_ :: (Unbox a, Monad m) => (a -> a -> m a) -> NonEmptyUVector a -> m ()
+ Data.Vector.NonEmpty.Unboxed: fold1M_ :: (Unbox a, Monad m) => (a -> a -> m a) -> NonEmptyUVector a -> m ()
+ Data.Vector.NonEmpty.Unboxed: foldM :: (Unbox b, Monad m) => (a -> b -> m a) -> a -> NonEmptyUVector b -> m a
+ Data.Vector.NonEmpty.Unboxed: foldM' :: (Unbox b, Monad m) => (a -> b -> m a) -> a -> NonEmptyUVector b -> m a
+ Data.Vector.NonEmpty.Unboxed: foldM'_ :: (Unbox b, Monad m) => (a -> b -> m a) -> a -> NonEmptyUVector b -> m ()
+ Data.Vector.NonEmpty.Unboxed: foldM_ :: (Unbox b, Monad m) => (a -> b -> m a) -> a -> NonEmptyUVector b -> m ()
+ Data.Vector.NonEmpty.Unboxed: foldl :: Unbox b => (a -> b -> a) -> a -> NonEmptyUVector b -> a
+ Data.Vector.NonEmpty.Unboxed: foldl' :: Unbox b => (a -> b -> a) -> a -> NonEmptyUVector b -> a
+ Data.Vector.NonEmpty.Unboxed: foldl1 :: Unbox a => (a -> a -> a) -> NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: foldl1' :: Unbox a => (a -> a -> a) -> NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: foldr :: Unbox a => (a -> b -> b) -> b -> NonEmptyUVector a -> b
+ Data.Vector.NonEmpty.Unboxed: foldr' :: Unbox a => (a -> b -> b) -> b -> NonEmptyUVector a -> b
+ Data.Vector.NonEmpty.Unboxed: foldr1 :: Unbox a => (a -> a -> a) -> NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: foldr1' :: Unbox a => (a -> a -> a) -> NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: forM :: (Unbox a, Unbox b, Monad m) => NonEmptyUVector a -> (a -> m b) -> m (NonEmptyUVector b)
+ Data.Vector.NonEmpty.Unboxed: forM_ :: (Unbox a, Monad m) => NonEmptyUVector a -> (a -> m b) -> m ()
+ Data.Vector.NonEmpty.Unboxed: force :: Unbox a => NonEmptyUVector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: fromList :: Unbox a => [a] -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: fromListN :: Unbox a => Int -> [a] -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: fromNonEmpty :: Unbox a => NonEmpty a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: fromNonEmptyN :: Unbox a => Int -> NonEmpty a -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: fromNonEmptyN1 :: Unbox a => Int -> NonEmpty a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: fromVector :: Unbox a => Vector a -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: generate :: Unbox a => Int -> (Int -> a) -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: generate1 :: Unbox a => Int -> (Int -> a) -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: generate1M :: (Monad m, Unbox a) => Int -> (Int -> m a) -> m (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: generateM :: (Monad m, Unbox a) => Int -> (Int -> m a) -> m (Maybe (NonEmptyUVector a))
+ Data.Vector.NonEmpty.Unboxed: group :: (Unbox a, Eq a) => NonEmptyUVector a -> NonEmpty (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: groupBy :: (Eq a, Unbox a) => (a -> a -> Bool) -> NonEmptyUVector a -> NonEmpty (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: head :: Unbox a => NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: headM :: (Monad m, Unbox a) => NonEmptyUVector a -> m a
+ Data.Vector.NonEmpty.Unboxed: ifilter :: Unbox a => (Int -> a -> Bool) -> NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: ifilterM :: (Unbox a, Monad m) => (Int -> a -> m Bool) -> NonEmptyUVector a -> m (Vector a)
+ Data.Vector.NonEmpty.Unboxed: ifoldM :: (Unbox b, Monad m) => (a -> Int -> b -> m a) -> a -> NonEmptyUVector b -> m a
+ Data.Vector.NonEmpty.Unboxed: ifoldM' :: (Unbox b, Monad m) => (a -> Int -> b -> m a) -> a -> NonEmptyUVector b -> m a
+ Data.Vector.NonEmpty.Unboxed: ifoldM'_ :: (Unbox b, Monad m) => (a -> Int -> b -> m a) -> a -> NonEmptyUVector b -> m ()
+ Data.Vector.NonEmpty.Unboxed: ifoldM_ :: (Unbox b, Monad m) => (a -> Int -> b -> m a) -> a -> NonEmptyUVector b -> m ()
+ Data.Vector.NonEmpty.Unboxed: ifoldl :: Unbox b => (a -> Int -> b -> a) -> a -> NonEmptyUVector b -> a
+ Data.Vector.NonEmpty.Unboxed: ifoldl' :: Unbox b => (a -> Int -> b -> a) -> a -> NonEmptyUVector b -> a
+ Data.Vector.NonEmpty.Unboxed: ifoldr :: Unbox a => (Int -> a -> b -> b) -> b -> NonEmptyUVector a -> b
+ Data.Vector.NonEmpty.Unboxed: ifoldr' :: Unbox a => (Int -> a -> b -> b) -> b -> NonEmptyUVector a -> b
+ Data.Vector.NonEmpty.Unboxed: imap :: (Unbox a, Unbox b) => (Int -> a -> b) -> NonEmptyUVector a -> NonEmptyUVector b
+ Data.Vector.NonEmpty.Unboxed: imapM :: (Unbox a, Unbox b, Monad m) => (Int -> a -> m b) -> NonEmptyUVector a -> m (NonEmptyUVector b)
+ Data.Vector.NonEmpty.Unboxed: imapM_ :: (Unbox a, Monad m) => (Int -> a -> m b) -> NonEmptyUVector a -> m ()
+ Data.Vector.NonEmpty.Unboxed: imapMaybe :: (Unbox a, Unbox b) => (Int -> a -> Maybe b) -> NonEmptyUVector a -> Vector b
+ Data.Vector.NonEmpty.Unboxed: indexM :: (Monad m, Unbox a) => NonEmptyUVector a -> Int -> m a
+ Data.Vector.NonEmpty.Unboxed: indexed :: Unbox a => NonEmptyUVector a -> NonEmptyUVector (Int, a)
+ Data.Vector.NonEmpty.Unboxed: init :: Unbox a => NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: intersperse :: Unbox a => a -> NonEmptyUVector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: iscanl :: (Unbox a, Unbox b) => (Int -> a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: iscanl' :: (Unbox a, Unbox b) => (Int -> a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: iscanr :: (Unbox a, Unbox b) => (Int -> a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b
+ Data.Vector.NonEmpty.Unboxed: iscanr' :: (Unbox a, Unbox b) => (Int -> a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b
+ Data.Vector.NonEmpty.Unboxed: iterateN :: Unbox a => Int -> (a -> a) -> a -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: iterateN1 :: Unbox a => Int -> (a -> a) -> a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: iterateN1M :: (Monad m, Unbox a) => Int -> (a -> m a) -> a -> m (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: iterateNM :: (Monad m, Unbox a) => Int -> (a -> m a) -> a -> m (Maybe (NonEmptyUVector a))
+ Data.Vector.NonEmpty.Unboxed: izipWith :: (Unbox a, Unbox b, Unbox c) => (Int -> a -> b -> c) -> NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c
+ Data.Vector.NonEmpty.Unboxed: izipWith3 :: (Unbox a, Unbox b, Unbox c, Unbox d) => (Int -> a -> b -> c -> d) -> NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector d
+ Data.Vector.NonEmpty.Unboxed: izipWith4 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e) => (Int -> a -> b -> c -> d -> e) -> NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector d -> NonEmptyUVector e
+ Data.Vector.NonEmpty.Unboxed: izipWith5 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f) => (Int -> a -> b -> c -> d -> e -> f) -> NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector d -> NonEmptyUVector e -> NonEmptyUVector f
+ Data.Vector.NonEmpty.Unboxed: izipWith6 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f, Unbox g) => (Int -> a -> b -> c -> d -> e -> f -> g) -> NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector d -> NonEmptyUVector e -> NonEmptyUVector f -> NonEmptyUVector g
+ Data.Vector.NonEmpty.Unboxed: izipWithM :: (Unbox a, Unbox b, Unbox c, Monad m) => (Int -> a -> b -> m c) -> NonEmptyUVector a -> NonEmptyUVector b -> m (NonEmptyUVector c)
+ Data.Vector.NonEmpty.Unboxed: izipWithM_ :: (Unbox a, Unbox b, Monad m) => (Int -> a -> b -> m c) -> NonEmptyUVector a -> NonEmptyUVector b -> m ()
+ Data.Vector.NonEmpty.Unboxed: last :: Unbox a => NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: lastM :: (Monad m, Unbox a) => NonEmptyUVector a -> m a
+ Data.Vector.NonEmpty.Unboxed: length :: Unbox a => NonEmptyUVector a -> Int
+ Data.Vector.NonEmpty.Unboxed: map :: (Unbox a, Unbox b) => (a -> b) -> NonEmptyUVector a -> NonEmptyUVector b
+ Data.Vector.NonEmpty.Unboxed: mapM :: (Unbox a, Unbox b, Monad m) => (a -> m b) -> NonEmptyUVector a -> m (NonEmptyUVector b)
+ Data.Vector.NonEmpty.Unboxed: mapM_ :: (Unbox a, Monad m) => (a -> m b) -> NonEmptyUVector a -> m ()
+ Data.Vector.NonEmpty.Unboxed: mapMaybe :: (Unbox a, Unbox b) => (a -> Maybe b) -> NonEmptyUVector a -> Vector b
+ Data.Vector.NonEmpty.Unboxed: maxIndex :: (Unbox a, Ord a) => NonEmptyUVector a -> Int
+ Data.Vector.NonEmpty.Unboxed: maxIndexBy :: Unbox a => (a -> a -> Ordering) -> NonEmptyUVector a -> Int
+ Data.Vector.NonEmpty.Unboxed: maximum :: (Unbox a, Ord a) => NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: maximumBy :: Unbox a => (a -> a -> Ordering) -> NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: minIndex :: (Unbox a, Ord a) => NonEmptyUVector a -> Int
+ Data.Vector.NonEmpty.Unboxed: minIndexBy :: Unbox a => (a -> a -> Ordering) -> NonEmptyUVector a -> Int
+ Data.Vector.NonEmpty.Unboxed: minimum :: (Unbox a, Ord a) => NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: minimumBy :: Unbox a => (a -> a -> Ordering) -> NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: modify :: Unbox a => (forall s. () => MVector s a -> ST s ()) -> NonEmptyUVector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: notElem :: (Unbox a, Eq a) => a -> NonEmptyUVector a -> Bool
+ Data.Vector.NonEmpty.Unboxed: or :: NonEmptyUVector Bool -> Bool
+ Data.Vector.NonEmpty.Unboxed: partition :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> (Vector a, Vector a)
+ Data.Vector.NonEmpty.Unboxed: partitionWith :: (Unbox a, Unbox b, Unbox c) => (a -> Either b c) -> NonEmptyUVector a -> (Vector b, Vector c)
+ Data.Vector.NonEmpty.Unboxed: postscanl :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: postscanl' :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: postscanr :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b
+ Data.Vector.NonEmpty.Unboxed: postscanr' :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b
+ Data.Vector.NonEmpty.Unboxed: prescanl :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: prescanl' :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: prescanr :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b
+ Data.Vector.NonEmpty.Unboxed: prescanr' :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b
+ Data.Vector.NonEmpty.Unboxed: product :: (Num a, Unbox a) => NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: replicate :: Unbox a => Int -> a -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: replicate1 :: Unbox a => Int -> a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: replicate1M :: (Monad m, Unbox a) => Int -> m a -> m (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: replicateM :: (Monad m, Unbox a) => Int -> m a -> m (Maybe (NonEmptyUVector a))
+ Data.Vector.NonEmpty.Unboxed: reverse :: Unbox a => NonEmptyUVector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: scanl :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: scanl' :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: scanl1 :: Unbox a => (a -> a -> a) -> NonEmptyUVector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: scanl1' :: Unbox a => (a -> a -> a) -> NonEmptyUVector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: scanr :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b
+ Data.Vector.NonEmpty.Unboxed: scanr' :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b
+ Data.Vector.NonEmpty.Unboxed: scanr1 :: Unbox a => (a -> a -> a) -> NonEmptyUVector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: scanr1' :: Unbox a => (a -> a -> a) -> NonEmptyUVector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: singleton :: Unbox a => a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: slice :: Unbox a => Int -> Int -> NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: snoc :: Unbox a => NonEmptyUVector a -> a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: snocV :: Unbox a => Vector a -> a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: span :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> (Vector a, Vector a)
+ Data.Vector.NonEmpty.Unboxed: splitAt :: Unbox a => Int -> NonEmptyUVector a -> (Vector a, Vector a)
+ Data.Vector.NonEmpty.Unboxed: sum :: (Num a, Unbox a) => NonEmptyUVector a -> a
+ Data.Vector.NonEmpty.Unboxed: tail :: Unbox a => NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: take :: Unbox a => Int -> NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: takeWhile :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: toList :: Unbox a => NonEmptyUVector a -> [a]
+ Data.Vector.NonEmpty.Unboxed: toNonEmpty :: Unbox a => NonEmptyUVector a -> NonEmpty a
+ Data.Vector.NonEmpty.Unboxed: toVector :: Unbox a => NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: uncons :: Unbox a => NonEmptyUVector a -> (a, Vector a)
+ Data.Vector.NonEmpty.Unboxed: unfoldr :: Unbox a => (b -> Maybe (a, b)) -> b -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: unfoldr1 :: Unbox a => (b -> Maybe (a, b)) -> a -> b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unfoldr1M :: (Monad m, Unbox a) => (b -> m (Maybe (a, b))) -> a -> b -> m (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: unfoldr1N :: Unbox a => Int -> (b -> Maybe (a, b)) -> a -> b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unfoldr1NM :: (Unbox a, Monad m) => Int -> (b -> m (Maybe (a, b))) -> a -> b -> m (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: unfoldrM :: (Unbox a, Monad m) => (b -> m (Maybe (a, b))) -> b -> m (Maybe (NonEmptyUVector a))
+ Data.Vector.NonEmpty.Unboxed: unfoldrN :: Unbox a => Int -> (b -> Maybe (a, b)) -> b -> Maybe (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: unfoldrNM :: (Unbox a, Monad m) => Int -> (b -> m (Maybe (a, b))) -> b -> m (Maybe (NonEmptyUVector a))
+ Data.Vector.NonEmpty.Unboxed: uniq :: (Unbox a, Eq a) => NonEmptyUVector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unsafeAccum :: (Unbox a, Unbox b) => (a -> b -> a) -> NonEmptyUVector a -> [(Int, b)] -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unsafeAccumulate :: (Unbox a, Unbox b) => (a -> b -> a) -> NonEmptyUVector a -> Vector (Int, b) -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unsafeAccumulate_ :: (Unbox a, Unbox b) => (a -> b -> a) -> NonEmptyUVector a -> Vector Int -> Vector b -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unsafeBackpermute :: Unbox a => NonEmptyUVector a -> NonEmptyUVector Int -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unsafeCreate :: Unbox a => (forall s. () => ST s (MVector s a)) -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unsafeCreateT :: (Traversable t, Unbox a) => (forall s. () => ST s (t (MVector s a))) -> t (NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed: unsafeDrop :: Unbox a => Int -> NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: unsafeFromList :: Unbox a => [a] -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unsafeFromVector :: Unbox a => Vector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unsafeIndex :: Unbox a => NonEmptyUVector a -> Int -> a
+ Data.Vector.NonEmpty.Unboxed: unsafeIndexM :: (Monad m, Unbox a) => NonEmptyUVector a -> Int -> m a
+ Data.Vector.NonEmpty.Unboxed: unsafeSlice :: Unbox a => Int -> Int -> NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: unsafeTake :: Unbox a => Int -> NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed: unsafeUpd :: Unbox a => NonEmptyUVector a -> [(Int, a)] -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unsafeUpdate :: Unbox a => NonEmptyUVector a -> Vector (Int, a) -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unsafeUpdate_ :: Unbox a => NonEmptyUVector a -> Vector Int -> Vector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: unsnoc :: Unbox a => NonEmptyUVector a -> (Vector a, a)
+ Data.Vector.NonEmpty.Unboxed: unstablePartition :: Unbox a => (a -> Bool) -> NonEmptyUVector a -> (Vector a, Vector a)
+ Data.Vector.NonEmpty.Unboxed: unzip :: (Unbox a, Unbox b) => NonEmptyUVector (a, b) -> (NonEmptyUVector a, NonEmptyUVector b)
+ Data.Vector.NonEmpty.Unboxed: unzip3 :: (Unbox a, Unbox b, Unbox c) => NonEmptyUVector (a, b, c) -> (NonEmptyUVector a, NonEmptyUVector b, NonEmptyUVector c)
+ Data.Vector.NonEmpty.Unboxed: unzip4 :: (Unbox a, Unbox b, Unbox c, Unbox d) => NonEmptyUVector (a, b, c, d) -> (NonEmptyUVector a, NonEmptyUVector b, NonEmptyUVector c, NonEmptyUVector d)
+ Data.Vector.NonEmpty.Unboxed: unzip5 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e) => NonEmptyUVector (a, b, c, d, e) -> (NonEmptyUVector a, NonEmptyUVector b, NonEmptyUVector c, NonEmptyUVector d, NonEmptyUVector e)
+ Data.Vector.NonEmpty.Unboxed: unzip6 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f) => NonEmptyUVector (a, b, c, d, e, f) -> (NonEmptyUVector a, NonEmptyUVector b, NonEmptyUVector c, NonEmptyUVector d, NonEmptyUVector e, NonEmptyUVector f)
+ Data.Vector.NonEmpty.Unboxed: update :: Unbox a => NonEmptyUVector a -> Vector (Int, a) -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: update_ :: Unbox a => NonEmptyUVector a -> Vector Int -> Vector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed: zip :: (Unbox a, Unbox b) => NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector (a, b)
+ Data.Vector.NonEmpty.Unboxed: zip3 :: (Unbox a, Unbox b, Unbox c) => NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector (a, b, c)
+ Data.Vector.NonEmpty.Unboxed: zip4 :: (Unbox a, Unbox b, Unbox c, Unbox d) => NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector d -> NonEmptyUVector (a, b, c, d)
+ Data.Vector.NonEmpty.Unboxed: zip5 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e) => NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector d -> NonEmptyUVector e -> NonEmptyUVector (a, b, c, d, e)
+ Data.Vector.NonEmpty.Unboxed: zip6 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f) => NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector d -> NonEmptyUVector e -> NonEmptyUVector f -> NonEmptyUVector (a, b, c, d, e, f)
+ Data.Vector.NonEmpty.Unboxed: zipWith :: (Unbox a, Unbox b, Unbox c) => (a -> b -> c) -> NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c
+ Data.Vector.NonEmpty.Unboxed: zipWith3 :: (Unbox a, Unbox b, Unbox c, Unbox d) => (a -> b -> c -> d) -> NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector d
+ Data.Vector.NonEmpty.Unboxed: zipWith4 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e) => (a -> b -> c -> d -> e) -> NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector d -> NonEmptyUVector e
+ Data.Vector.NonEmpty.Unboxed: zipWith5 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f) => (a -> b -> c -> d -> e -> f) -> NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector d -> NonEmptyUVector e -> NonEmptyUVector f
+ Data.Vector.NonEmpty.Unboxed: zipWith6 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f, Unbox g) => (a -> b -> c -> d -> e -> f -> g) -> NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector c -> NonEmptyUVector d -> NonEmptyUVector e -> NonEmptyUVector f -> NonEmptyUVector g
+ Data.Vector.NonEmpty.Unboxed: zipWithM :: (Unbox a, Unbox b, Unbox c, Monad m) => (a -> b -> m c) -> NonEmptyUVector a -> NonEmptyUVector b -> m (NonEmptyUVector c)
+ Data.Vector.NonEmpty.Unboxed: zipWithM_ :: (Unbox a, Unbox b, Monad m) => (a -> b -> m c) -> NonEmptyUVector a -> NonEmptyUVector b -> m ()
+ Data.Vector.NonEmpty.Unboxed.Internal: NonEmptyMUVector :: MVector s a -> NonEmptyMUVector s a
+ Data.Vector.NonEmpty.Unboxed.Internal: NonEmptyUVector :: Vector a -> NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed.Internal: [_neUvec] :: NonEmptyUVector a -> Vector a
+ Data.Vector.NonEmpty.Unboxed.Internal: [_nemUvec] :: NonEmptyMUVector s a -> MVector s a
+ Data.Vector.NonEmpty.Unboxed.Internal: instance (Data.Data.Data a, Data.Vector.Unboxed.Base.Unbox a) => Data.Data.Data (Data.Vector.NonEmpty.Unboxed.Internal.NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed.Internal: instance (Data.Vector.Unboxed.Base.Unbox a, GHC.Classes.Eq a) => GHC.Classes.Eq (Data.Vector.NonEmpty.Unboxed.Internal.NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed.Internal: instance (Data.Vector.Unboxed.Base.Unbox a, GHC.Classes.Ord a) => GHC.Classes.Ord (Data.Vector.NonEmpty.Unboxed.Internal.NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed.Internal: instance (Data.Vector.Unboxed.Base.Unbox a, GHC.Read.Read a) => GHC.Read.Read (Data.Vector.NonEmpty.Unboxed.Internal.NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed.Internal: instance (GHC.Show.Show a, Data.Vector.Unboxed.Base.Unbox a) => GHC.Show.Show (Data.Vector.NonEmpty.Unboxed.Internal.NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed.Internal: instance Control.DeepSeq.NFData (Data.Vector.NonEmpty.Unboxed.Internal.NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed.Internal: instance Data.Vector.Unboxed.Base.Unbox a => GHC.Base.Semigroup (Data.Vector.NonEmpty.Unboxed.Internal.NonEmptyUVector a)
+ Data.Vector.NonEmpty.Unboxed.Internal: newtype NonEmptyMUVector s a
+ Data.Vector.NonEmpty.Unboxed.Internal: newtype NonEmptyUVector a
+ Data.Vector.NonEmpty.Unboxed.Internal: type NonEmptyIOUVector = NonEmptyMUVector RealWorld
+ Data.Vector.NonEmpty.Unboxed.Internal: type NonEmptySTUVector s = NonEmptyMUVector s
+ Data.Vector.NonEmpty.Unboxed.Mutable: clear :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> m ()
+ Data.Vector.NonEmpty.Unboxed.Mutable: clone :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> m (NonEmptyMUVector (PrimState m) a)
+ Data.Vector.NonEmpty.Unboxed.Mutable: copy :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> NonEmptyMUVector (PrimState m) a -> m ()
+ Data.Vector.NonEmpty.Unboxed.Mutable: data NonEmptyMUVector s a
+ Data.Vector.NonEmpty.Unboxed.Mutable: drop :: Unbox a => Int -> NonEmptyMUVector s a -> MVector s a
+ Data.Vector.NonEmpty.Unboxed.Mutable: fromMVector :: Unbox a => MVector s a -> Maybe (NonEmptyMUVector s a)
+ Data.Vector.NonEmpty.Unboxed.Mutable: grow :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> Int -> m (NonEmptyMUVector (PrimState m) a)
+ Data.Vector.NonEmpty.Unboxed.Mutable: init :: Unbox a => NonEmptyMUVector s a -> MVector s a
+ Data.Vector.NonEmpty.Unboxed.Mutable: length :: Unbox a => NonEmptyMUVector s a -> Int
+ Data.Vector.NonEmpty.Unboxed.Mutable: modify :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> (a -> a) -> Int -> m ()
+ Data.Vector.NonEmpty.Unboxed.Mutable: move :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> NonEmptyMUVector (PrimState m) a -> m ()
+ Data.Vector.NonEmpty.Unboxed.Mutable: new :: (PrimMonad m, Unbox a) => Int -> m (Maybe (NonEmptyMUVector (PrimState m) a))
+ Data.Vector.NonEmpty.Unboxed.Mutable: new1 :: (PrimMonad m, Unbox a) => Int -> m (NonEmptyMUVector (PrimState m) a)
+ Data.Vector.NonEmpty.Unboxed.Mutable: nextPermutation :: (PrimMonad m, Ord e, Unbox e) => NonEmptyMUVector (PrimState m) e -> m Bool
+ Data.Vector.NonEmpty.Unboxed.Mutable: overlaps :: Unbox a => NonEmptyMUVector s a -> NonEmptyMUVector s a -> Bool
+ Data.Vector.NonEmpty.Unboxed.Mutable: read :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> Int -> m a
+ Data.Vector.NonEmpty.Unboxed.Mutable: replicate :: (PrimMonad m, Unbox a) => Int -> a -> m (Maybe (NonEmptyMUVector (PrimState m) a))
+ Data.Vector.NonEmpty.Unboxed.Mutable: replicate1 :: (PrimMonad m, Unbox a) => Int -> a -> m (NonEmptyMUVector (PrimState m) a)
+ Data.Vector.NonEmpty.Unboxed.Mutable: replicate1M :: (PrimMonad m, Unbox a) => Int -> m a -> m (Maybe (NonEmptyMUVector (PrimState m) a))
+ Data.Vector.NonEmpty.Unboxed.Mutable: replicateM :: (PrimMonad m, Unbox a) => Int -> m a -> m (Maybe (NonEmptyMUVector (PrimState m) a))
+ Data.Vector.NonEmpty.Unboxed.Mutable: set :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> a -> m ()
+ Data.Vector.NonEmpty.Unboxed.Mutable: slice :: Unbox a => Int -> Int -> NonEmptyMUVector s a -> MVector s a
+ Data.Vector.NonEmpty.Unboxed.Mutable: splitAt :: Unbox a => Int -> NonEmptyMUVector s a -> (MVector s a, MVector s a)
+ Data.Vector.NonEmpty.Unboxed.Mutable: swap :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> Int -> Int -> m ()
+ Data.Vector.NonEmpty.Unboxed.Mutable: tail :: Unbox a => NonEmptyMUVector s a -> MVector s a
+ Data.Vector.NonEmpty.Unboxed.Mutable: take :: Unbox a => Int -> NonEmptyMUVector s a -> MVector s a
+ Data.Vector.NonEmpty.Unboxed.Mutable: toMVector :: Unbox a => NonEmptyMUVector s a -> MVector s a
+ Data.Vector.NonEmpty.Unboxed.Mutable: type NonEmptyIOUVector = NonEmptyMUVector RealWorld
+ Data.Vector.NonEmpty.Unboxed.Mutable: type NonEmptySTUVector s = NonEmptyMUVector s
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeCopy :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> NonEmptyMUVector (PrimState m) a -> m ()
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeDrop :: Unbox a => Int -> NonEmptyMUVector s a -> MVector s a
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeFromMVector :: Unbox a => MVector s a -> NonEmptyMUVector s a
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeGrow :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> Int -> m (NonEmptyMUVector (PrimState m) a)
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeModify :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> (a -> a) -> Int -> m ()
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeMove :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> NonEmptyMUVector (PrimState m) a -> m ()
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeNew :: (PrimMonad m, Unbox a) => Int -> m (Maybe (NonEmptyMUVector (PrimState m) a))
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeRead :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> Int -> m a
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeSlice :: Unbox a => Int -> Int -> NonEmptyMUVector s a -> MVector s a
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeSwap :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> Int -> Int -> m ()
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeTake :: Unbox a => Int -> NonEmptyMUVector s a -> MVector s a
+ Data.Vector.NonEmpty.Unboxed.Mutable: unsafeWrite :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> Int -> a -> m ()
+ Data.Vector.NonEmpty.Unboxed.Mutable: write :: (PrimMonad m, Unbox a) => NonEmptyMUVector (PrimState m) a -> Int -> a -> m ()
Files
- CHANGELOG.md +10/−0
- README.md +14/−2
- nonempty-vector.cabal +15/−1
- src/Data/Vector/NonEmpty/Internal.hs +39/−18
- src/Data/Vector/NonEmpty/Unboxed.hs +2768/−0
- src/Data/Vector/NonEmpty/Unboxed/Internal.hs +110/−0
- src/Data/Vector/NonEmpty/Unboxed/Mutable.hs +452/−0
- test/Main.hs +23/−1
- test/Test/Data/Vector/NonEmpty/AccessorsU.hs +181/−0
- test/Test/Data/Vector/NonEmpty/ConstructionU.hs +316/−0
- test/Test/Data/Vector/NonEmpty/ConversionU.hs +115/−0
- test/Test/Data/Vector/NonEmpty/ElementwiseU.hs +288/−0
- test/Test/Data/Vector/NonEmpty/FoldsU.hs +285/−0
- test/Test/Data/Vector/NonEmpty/GroupingU.hs +107/−0
- test/Test/Data/Vector/NonEmpty/InstancesU.hs +142/−0
- test/Test/Data/Vector/NonEmpty/ModificationU.hs +184/−0
- test/Test/Data/Vector/NonEmpty/MutableU.hs +440/−0
- test/Test/Data/Vector/NonEmpty/PredicatesU.hs +192/−0
- test/Test/Data/Vector/NonEmpty/ScansU.hs +215/−0
- test/Test/Data/Vector/NonEmpty/Util.hs +64/−1
CHANGELOG.md view
@@ -1,5 +1,15 @@ # Revision history for nonempty-vector +## 1.0++* Add immutable and mutable unboxed non-empty vectors in+ `Data.Vector.NonEmpty.Unboxed` and `Data.Vector.NonEmpty.Unboxed.Mutable`.+ Constructors are available through `Data.Vector.NonEmpty.Unboxed.Internal`.+* Add property tests for the unboxed API+* Delegate boxed `Foldable` methods to the underlying vector and specialize+ `Foldable1` operations, including strict folding and non-empty conversion.++Thanks to Koz Ross (@kozross) for the unboxed API! ## 0.3 * Add `group` and `groupBy`, returning non-empty lists of non-empty vector slices.
README.md view
@@ -2,6 +2,18 @@  [](https://hackage.haskell.org/package/nonempty-vector) -This package presents thin wrappers around mutable and immutable [Data.Vector](https://hackage.haskell.org/package/vector) types that enforce non-emptiness. The entire Vector API is supported for both sets of boxed vectors, with future plans to support unboxed, primitive, storable, and generic vectors.+This package provides thin wrappers around mutable and immutable+[vector](https://hackage.haskell.org/package/vector) types that enforce+non-emptiness, with APIs for both boxed and unboxed storage. -There are no external dependencies that are not already in `base`.+| Storage | Immutable | Mutable |+| --- | --- | --- |+| Boxed | `Data.Vector.NonEmpty` | `Data.Vector.NonEmpty.Mutable` |+| Unboxed | `Data.Vector.NonEmpty.Unboxed` | `Data.Vector.NonEmpty.Unboxed.Mutable` |++The unboxed API requires `Unbox` instances for element types. Operations that can+produce an empty result return an ordinary vector or `Maybe`, as appropriate.+The `Internal` modules expose constructors for users who manage the non-emptiness+invariant themselves.++Library dependencies are `base`, `deepseq`, `primitive`, and `vector`.
nonempty-vector.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: nonempty-vector-version: 0.3+version: 1.0 synopsis: Non-empty vectors description: Performant, non-empty mutable and immutable vectors homepage: https://github.com/emilypi/nonempty-vector@@ -31,8 +31,11 @@ library exposed-modules: Data.Vector.NonEmpty+ Data.Vector.NonEmpty.Unboxed Data.Vector.NonEmpty.Internal Data.Vector.NonEmpty.Mutable+ Data.Vector.NonEmpty.Unboxed.Mutable+ Data.Vector.NonEmpty.Unboxed.Internal build-depends: base >=4.16 && <4.23@@ -50,16 +53,27 @@ main-is: Main.hs other-modules: Test.Data.Vector.NonEmpty.Accessors+ Test.Data.Vector.NonEmpty.AccessorsU Test.Data.Vector.NonEmpty.Construction+ Test.Data.Vector.NonEmpty.ConstructionU Test.Data.Vector.NonEmpty.Conversion+ Test.Data.Vector.NonEmpty.ConversionU Test.Data.Vector.NonEmpty.Elementwise+ Test.Data.Vector.NonEmpty.ElementwiseU Test.Data.Vector.NonEmpty.Folds+ Test.Data.Vector.NonEmpty.FoldsU Test.Data.Vector.NonEmpty.Grouping+ Test.Data.Vector.NonEmpty.GroupingU Test.Data.Vector.NonEmpty.Instances+ Test.Data.Vector.NonEmpty.InstancesU Test.Data.Vector.NonEmpty.Modification+ Test.Data.Vector.NonEmpty.ModificationU Test.Data.Vector.NonEmpty.Mutable+ Test.Data.Vector.NonEmpty.MutableU Test.Data.Vector.NonEmpty.Predicates+ Test.Data.Vector.NonEmpty.PredicatesU Test.Data.Vector.NonEmpty.Scans+ Test.Data.Vector.NonEmpty.ScansU Test.Data.Vector.NonEmpty.Util build-depends:
src/Data/Vector/NonEmpty/Internal.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-} -- |@@ -37,6 +38,7 @@ import Data.Data (Data) import qualified Data.Foldable as Foldable+import Data.List.NonEmpty (NonEmpty((:|))) #if MIN_VERSION_base(4,18,0) import Data.Foldable1 (Foldable1) import qualified Data.Foldable1 as Foldable1@@ -76,6 +78,7 @@ , Functor, Applicative, Monad , MonadZip , Semigroup+ , Traversable ) instance Show a => Show (NonEmptyVector a) where@@ -93,28 +96,46 @@ instance Foldable NonEmptyVector where foldMap f = Foldable.foldMap f . _neVec+ foldr f x = Foldable.foldr f x . _neVec+ foldl f x = Foldable.foldl f x . _neVec+ foldr1 f = Foldable.foldr1 f . _neVec+ foldl1 f = Foldable.foldl1 f . _neVec+ foldr' f x = Foldable.foldr' f x . _neVec+ foldl' f x = Foldable.foldl' f x . _neVec+ toList = Foldable.toList . _neVec+ length = Foldable.length . _neVec+ null = const False+ elem x = Foldable.elem x . _neVec+ maximum = Foldable.maximum . _neVec+ minimum = Foldable.minimum . _neVec+ sum = Foldable.sum . _neVec+ product = Foldable.product . _neVec #if MIN_VERSION_base(4,18,0) instance Foldable1 NonEmptyVector where- foldMap1 f (NonEmptyVector v) =- let- h = V.unsafeHead v -- guaranteed head (nonemptiness)- t = V.unsafeTail v -- guaranteed possibly empty tail- in go (f h) t -- therefore this is a sound call- where- go x xs- -- when xs is empty, vector is exhausted, return x- | V.null xs = x- | otherwise =- -- if xs is not empty, then there are at least 2 elements in the list. Hence, h and t are sound calls to make.- let- h = V.unsafeHead xs- t = V.unsafeTail xs- in x <> go (f h) t+ foldMap1 f (NonEmptyVector v) = + let + projected = fmap f v+ h = V.unsafeHead projected -- guaranteed head (nonemptiness)+ t = V.unsafeTail projected -- guaranteed possibly empty tail+ -- Defer to `Vector`'s underlying folding mechanism.+ -- Direction doesn't matter since we're associative anyway.+ in V.foldl (<>) h t+ foldMap1' f (NonEmptyVector v) = + let + projected = fmap f v+ h = V.unsafeHead projected+ t = V.unsafeTail projected+ in V.foldl' (<>) h t+ toNonEmpty (NonEmptyVector v) = + let h = V.unsafeHead v+ t = V.unsafeTail v+ in h :| V.toList t+ maximum = V.maximum . _neVec+ minimum = V.minimum . _neVec+ head = V.unsafeHead . _neVec+ last (NonEmptyVector v) = V.unsafeIndex v (V.length v - 1) #endif--instance Traversable NonEmptyVector where- traverse f = fmap NonEmptyVector . traverse f . _neVec -- ---------------------------------------------------------------------- -- -- Non-empty mutable vectors
+ src/Data/Vector/NonEmpty/Unboxed.hs view
@@ -0,0 +1,2768 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE CPP #-}+-- |+-- Module : Data.Vector.NonEmpty.Unboxed+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : Experimental+-- Portability : DataTypeable, CPP+--+-- A library for non-empty unboxed vectors (that is, polymorphic arrays capable of+-- holding any value whose type has an 'V.Unbox' isntance). Non-empty vectors come in +-- two flavors:+--+-- * mutable+--+-- * immutable+--+-- This library attempts to provide support for all standard 'Vector' operations+-- in the API, with some slight variation in types and implementation. For example,+-- since 'head' and 'foldr' are always guaranteed to be over a non-empty 'Vector',+-- it is safe to make use of the 'unsafe-*' 'Vector' operations and semigroupal+-- folds available in the API in lieu of the standard implementations.+--+-- In contrast, some operations such as 'filter' may "break out" of a t'NonEmptyUVector'+-- due to the fact that there are no guarantees that may be made on the types of+-- 'Bool'-valued functions passed in, hence one could write the following:+--+-- @+-- filter (const false) v+-- @+--+-- which always produces an empty vector. Thus, some operations must return either+-- a 'Maybe' containing a t'NonEmptyUVector' or a 'Vector' whenever appropriate. Generally+-- The former is used in initialization and generation operations, and the latter+-- is used in iterative operations where the intent is not to create an instance+-- of t'NonEmptyUVector'.+--+-- Credit to Roman Leshchinskiy for the original Vector library upon which this is based.+--+module Data.Vector.NonEmpty.Unboxed+( -- * Boxed non-empty vectors+ NonEmptyUVector++ -- * Accessors++ -- ** Length information+, length++ -- ** Indexing+, head, last, (!), (!?)+, unsafeIndex++ -- ** Monadic Indexing+, headM, lastM, indexM, unsafeIndexM++ -- ** Extracting subvectors (slicing)+, tail, slice, init, take, drop+, uncons, unsnoc, splitAt+, unsafeSlice, unsafeTake, unsafeDrop++ -- * 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, (++), concat, concat1++ -- ** Restricting memory usage+, force++ -- * Conversion++ -- ** To/from non-empty lists+, toNonEmpty, fromNonEmpty+, fromNonEmptyN, fromNonEmptyN1+, unsafeFromList++ -- ** To/from vector+, toVector, fromVector, unsafeFromVector++ -- ** To/from list+, toList, fromList, fromListN++ -- * Modifying non-empty vectors++ -- ** Bulk Updates+, (//), update, update_+, unsafeUpd, unsafeUpdate, unsafeUpdate_++ -- * Accumulations+, accum, accumulate, accumulate_+, unsafeAccum, unsafeAccumulate, unsafeAccumulate_++ -- * Permutations+, reverse, backpermute, unsafeBackpermute++ -- * Safe destructive updates+, modify++ -- * Elementwise operations++ -- ** Indexing+, indexed++ -- ** Mapping+, map, imap, concatMap++ -- ** Monadic mapping+, mapM, imapM, mapM_, imapM_+, forM, forM_++ -- ** Zipping+, zipWith, zipWith3, zipWith4, zipWith5, zipWith6+, izipWith, izipWith3, izipWith4, izipWith5, izipWith6+, zip, zip3, zip4, zip5, zip6++ -- ** Monadic Zipping+, zipWithM, zipWithM_, izipWithM, izipWithM_++ -- ** Unzipping+, unzip, unzip3, unzip4, unzip5, unzip6++ -- * Working with predicates++ -- ** Filtering+, uniq, mapMaybe, imapMaybe+, filter, ifilter, filterM, ifilterM+, takeWhile, dropWhile++ -- * Partitioning+, partition, partitionWith, unstablePartition, span, break++ -- * Searching+, elem, notElem, find, findIndex, findIndices, elemIndex+, elemIndices++ -- * Folding+, foldl, foldl1, foldl', foldl1'+, foldr, foldr1, foldr', foldr1'+, ifoldl, ifoldl', ifoldr, ifoldr'++ -- * Specialized folds+, all, any, and, or, sum, product+, maximum, maximumBy, minimum, minimumBy+, maxIndex, maxIndexBy, minIndex, minIndexBy++ -- * Monadic Folds+, foldM, foldM', fold1M, fold1M', foldM_, foldM'_, fold1M_+, fold1M'_, ifoldM, ifoldM', ifoldM_, ifoldM'_++ -- * Prefix sums (scans)+, prescanl, prescanl', postscanl, postscanl'+, scanl, scanl', scanl1, scanl1', iscanl, iscanl'+, prescanr, prescanr', postscanr, postscanr'+, scanr, scanr', scanr1, scanr1', iscanr, iscanr'++ -- ** Transformations+, intersperse++ -- ** Grouping+, group+, groupBy++) where+++import Prelude ( Bool, Eq, Ord, Num, Enum+ , (.), Ordering, max, uncurry, snd+ , pure, (+), otherwise, (>=), (-), (*), ($), (<=)+ , (==), not)++import Control.Monad (Monad)+import Control.Monad.ST++import qualified Data.Foldable as Foldable+import Data.Either (Either(..))+#if MIN_VERSION_base(4,19,0)+-- This import will only execute if compiling with base >= 4.19.0.0 (GHC 9.8+)+import Data.Functor hiding (unzip)+#else+import Data.Functor+#endif+import Data.Int+import Data.List.NonEmpty (NonEmpty(..), (<|))+import qualified Data.List.NonEmpty as NonEmpty+import Data.Kind (Type)+import Data.Maybe (Maybe(..))+import Data.Semigroup (Semigroup(..), (<>))+import Data.Traversable (Traversable)+import Data.Vector.Unboxed (Vector)+import qualified Data.Vector.Unboxed as V+import qualified Data.Vector.Generic as G+import Data.Vector.Unboxed.Mutable (MVector, unsafeWrite)+import Data.Vector.NonEmpty.Unboxed.Internal+++-- $setup+-- >>> import Prelude (Int, String, ($), (.), (+), (<), const, return, Maybe(..), Either(..))+-- >>> import Data.Bool+-- >>> import Data.Eq+-- >>> import qualified Prelude as P+-- >>> import qualified Data.Vector.Unboxed as V+-- >>> import Data.List.NonEmpty (NonEmpty(..))+-- >>> import qualified Data.List.NonEmpty as NEL+-- >>> :set -XTypeApplications+-- >>> :set -XScopedTypeVariables++-- ---------------------------------------------------------------------- --+-- Accessors + Indexing++-- | /O(1)/ Length.+--+-- >>> length $ unsafeFromList [1..10]+-- 10+--+length :: V.Unbox a => NonEmptyUVector a -> Int+length = V.length . _neUvec+{-# INLINE length #-}++-- | /O(1)/ First element. Since head is guaranteed, bounds checks+-- are bypassed by deferring to 'Data.Vector.unsafeHead'.+--+--+-- >>> head $ unsafeFromList [1..10]+-- 1+--+head :: V.Unbox a => NonEmptyUVector a -> a+head = V.unsafeHead . _neUvec+{-# INLINE head #-}++-- | /O(1)/ Last element. Since a last element is guaranteed, bounds checks+-- are bypassed by deferring to 'Data.Vector.unsafeLast'.+--+--+-- >>> last $ unsafeFromList [1..10]+-- 10+--+last :: V.Unbox a => NonEmptyUVector a -> a+last = V.unsafeLast . _neUvec+{-# INLINE last #-}++-- | /O(1)/ Indexing.+--+--+-- >>> (unsafeFromList [1..10]) ! 0+-- 1+--+(!) :: V.Unbox a => NonEmptyUVector a -> Int -> a+(!) (NonEmptyUVector as) n = as V.! n+{-# INLINE (!) #-}++-- | /O(1)/ Safe indexing.+--+--+-- >>> (unsafeFromList [1..10]) !? 0+-- Just 1+--+-- >>> (unsafeFromList [1..10]) !? 11+-- Nothing+--+(!?) :: V.Unbox a => NonEmptyUVector a -> Int -> Maybe a+(NonEmptyUVector as) !? n = as V.!? n+{-# INLINE (!?) #-}++-- | /O(1)/ Unsafe indexing without bounds checking+--+unsafeIndex :: V.Unbox a => NonEmptyUVector a -> Int -> a+unsafeIndex (NonEmptyUVector as) n = V.unsafeIndex as n+{-# INLINE unsafeIndex #-}++-- ---------------------------------------------------------------------- --+-- Monadic Indexing++-- | /O(1)/ Indexing in a monad.+--+-- The monad allows operations to be strict in the non-empty vector when+-- necessary.+--+-- See 'Data.Vector.indexM' for more details+--+--+-- >>> indexM @[] (unsafeFromList [1..10]) 3+-- [4]+--+indexM :: (Monad m, V.Unbox a) => NonEmptyUVector a -> Int -> m a+indexM (NonEmptyUVector v) n = V.indexM v n+{-# INLINE indexM #-}++-- | /O(1)/ First element of a non-empty vector in a monad.+--+-- See 'Data.Vector.indexM' for an explanation of why this is useful.+--+-- Note that this function defers to 'Data.Vector.unsafeHeadM' since head is+-- guaranteed to be safe by construction.+--+--+-- >>> headM @[] (unsafeFromList [1..10])+-- [1]+--+headM :: (Monad m, V.Unbox a) => NonEmptyUVector a -> m a+headM (NonEmptyUVector v) = V.unsafeHeadM v+{-# INLINE headM #-}++-- | /O(1)/ Last element of a non-empty vector in a monad. See 'Data.Vector.indexM'+-- for an explanation of why this is useful.+--+-- Note that this function defers to 'Data.Vector.unsafeLastM' since a last element is+-- guaranteed.+--+--+-- >>> lastM @[] (unsafeFromList [1..10])+-- [10]+--+lastM :: (Monad m, V.Unbox a) => NonEmptyUVector a -> m a+lastM (NonEmptyUVector v) = V.unsafeLastM v+{-# INLINE lastM #-}++-- | O(1) Indexing in a monad without bounds checks. See 'indexM' for an+-- explanation of why this is useful.+--+unsafeIndexM :: (Monad m, V.Unbox a) => NonEmptyUVector a -> Int -> m a+unsafeIndexM (NonEmptyUVector v) n = V.unsafeIndexM v n+{-# INLINE unsafeIndexM #-}++-- ---------------------------------------------------------------------- --+-- Extracting subvectors (slicing)++-- | /O(1)/ Yield all but the first element without copying. Since the+-- vector returned may be empty (i.e. input was a singleton), this function+-- returns a normal 'Vector'+--+--+-- >>> tail (unsafeFromList [1..10])+-- [2,3,4,5,6,7,8,9,10]+--+tail :: V.Unbox a => NonEmptyUVector a -> Vector a+tail = V.unsafeTail . _neUvec+{-# INLINE tail #-}++-- | /O(1)/ Yield a slice of a non-empty vector without copying at+-- the @0@th and @1@st indices.+--+--+-- >>> uncons (unsafeFromList [1..10])+-- (1,[2,3,4,5,6,7,8,9,10])+--+uncons :: V.Unbox a => NonEmptyUVector a -> (a, Vector a)+uncons v = (head v, tail v)+{-# INLINE uncons #-}++-- | /O(1)/ Yield a slice of a non-empty vector without copying at+-- the @n-1@th and @nth@ indices+--+--+-- >>> unsnoc (unsafeFromList [1..10])+-- ([1,2,3,4,5,6,7,8,9],10)+--+unsnoc :: V.Unbox a => NonEmptyUVector a -> (Vector a, a)+unsnoc v = (init v, last v)+{-# INLINE unsnoc #-}++-- | /O(1)/ Yield a slice of the non-empty vector without copying it.+-- The vector must contain at least i+n elements. Because this is not+-- guaranteed, this function returns a 'Vector' which could be empty+--+--+-- >>> slice 0 3 (unsafeFromList [1..10])+-- [1,2,3]+--+slice :: V.Unbox a => Int -> Int -> NonEmptyUVector a -> Vector a+slice i n = V.slice i n . _neUvec+{-# INLINE slice #-}++-- | /O(1)/ Yield all but the last element without copying. Since the+-- vector returned may be empty (i.e. input was a singleton), this function+-- returns a normal 'Vector'+--+--+-- >>> init (unsafeFromList [1..3])+-- [1,2]+--+init :: V.Unbox a => NonEmptyUVector a -> Vector a+init = V.unsafeInit . _neUvec+{-# INLINE init #-}++-- | /O(1)/ Yield at the first n elements without copying. The non-empty vector may+-- contain less than n elements in which case it is returned as a vector unchanged.+--+--+-- >>> take 2 (unsafeFromList [1..3])+-- [1,2]+--+take :: V.Unbox a => Int -> NonEmptyUVector a -> Vector a+take n = V.take n . _neUvec+{-# INLINE take #-}++-- | /O(1)/ Yield all but the first n elements without copying. The non-empty vector+-- may contain less than n elements in which case an empty vector is returned.+--+--+-- >>> drop 2 (unsafeFromList [1..3])+-- [3]+--+drop :: V.Unbox a => Int -> NonEmptyUVector a -> Vector a+drop n = V.drop n . _neUvec+{-# INLINE drop #-}++-- | /O(1)/ Yield the first n elements paired with the remainder without copying.+--+-- This function returns a pair of vectors, as one may slice a (0, n+1).+--+--+-- >>> splitAt 2 (unsafeFromList [1..3])+-- ([1,2],[3])+--+splitAt :: V.Unbox a => Int -> NonEmptyUVector a -> (Vector a, Vector a)+splitAt n = V.splitAt n . _neUvec+{-# INLINE splitAt #-}++-- | /O(1)/ Yield a slice of the vector without copying. The vector must contain at+-- least i+n elements but this is not checked.+--+unsafeSlice :: V.Unbox a => Int -> Int -> NonEmptyUVector a -> Vector a+unsafeSlice i n = V.unsafeSlice i n . _neUvec+{-# INLINE unsafeSlice #-}++-- | /O(1)/ Yield the first n elements without copying. The vector must contain at+-- least n elements but this is not checked.+--+unsafeTake :: V.Unbox a => Int -> NonEmptyUVector a -> Vector a+unsafeTake n = V.unsafeTake n . _neUvec+{-# INLINE unsafeTake #-}++-- | /O(1)/ Yield all but the first n elements without copying. The vector must contain+-- at least n elements but this is not checked.+--+unsafeDrop :: V.Unbox a => Int -> NonEmptyUVector a -> Vector a+unsafeDrop n = V.unsafeDrop n . _neUvec+{-# INLINE unsafeDrop #-}++-- ---------------------------------------------------------------------- --+-- Construction++-- | /O(1)/ Non-empty vector with exactly one element+--+--+-- >>> singleton "a"+-- ["a"]+--+singleton :: V.Unbox a => a -> NonEmptyUVector a+singleton = NonEmptyUVector . V.singleton+{-# INLINE singleton #-}++-- | /O(n)/ Non-empty vector of the given length with the same value in+-- each position.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--+-- >>> replicate 3 "a"+-- Just ["a","a","a"]+--+-- >>> replicate 0 "a"+-- Nothing+--+replicate :: V.Unbox a => Int -> a -> Maybe (NonEmptyUVector a)+replicate n a = fromVector (V.replicate n a)+{-# INLINE replicate #-}++-- | /O(n)/ Non-empty vector of the given length with the same value in+-- each position.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--+-- >>> replicate1 3 "a"+-- ["a","a","a"]+--+-- >>> replicate1 0 "a"+-- ["a"]+--+-- >>> replicate1 (-1) "a"+-- ["a"]+--+replicate1 :: V.Unbox a => Int -> a -> NonEmptyUVector a+replicate1 n a = unsafeFromVector (V.replicate (max n 1) a)+{-# INLINE replicate1 #-}++-- | /O(n)/ Construct a vector of the given length by applying the function to+-- each index.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--+-- >>> let f 0 = "a"; f _ = "k"; f :: Int -> String+--+-- >>> generate 1 f+-- Just ["a"]+--+-- >>> generate 0 f+-- Nothing+--+-- >>> generate 2 f+-- Just ["a","k"]+--+generate :: V.Unbox a => Int -> (Int -> a) -> Maybe (NonEmptyUVector a)+generate n f = fromVector (V.generate n f)+{-# INLINE generate #-}++-- | /O(n)/ Construct a vector of the given length by applying the function to+-- each index.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--+-- >>> let f 0 = "a"; f _ = "k"; f :: Int -> String+--+-- >>> generate1 2 f+-- ["a","k"]+--+-- >>> generate1 0 f+-- ["a"]+--+-- >>> generate1 (-1) f+-- ["a"]+--+generate1 :: V.Unbox a => Int -> (Int -> a) -> NonEmptyUVector a+generate1 n f = unsafeFromVector (V.generate (max n 1) f)+{-# INLINE generate1 #-}++-- | /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'.+--+-- >>> iterateN 3 (+1) 0+-- Just [0,1,2]+--+-- >>> iterateN 0 (+1) 0+-- Nothing+--+-- >>> iterateN (-1) (+1) 0+-- Nothing+--+iterateN :: V.Unbox a => Int -> (a -> a) -> a -> Maybe (NonEmptyUVector a)+iterateN n f a = fromVector (V.iterateN n f a)+{-# INLINE iterateN #-}++-- | /O(n)/ Apply function n times to value. Zeroth element is original value.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--+-- >>> iterateN1 3 (+1) 0+-- [0,1,2]+--+-- >>> iterateN1 0 (+1) 0+-- [0]+--+-- >>> iterateN1 (-1) (+1) 0+-- [0]+--+iterateN1 :: V.Unbox a => Int -> (a -> a) -> a -> NonEmptyUVector a+iterateN1 n f a = unsafeFromVector (V.iterateN (max n 1) f a)+{-# INLINE iterateN1 #-}++-- ---------------------------------------------------------------------- --+-- Monadic Initialization++-- | /O(n)/ Execute the monadic action the given number of times and store+-- the results in a vector.+--+-- When given a index n <= 0, then 'Nothing' is returned, otherwise 'Just'.+--+--+-- >>> replicateM @Maybe 3 (Just "a")+-- Just (Just ["a","a","a"])+--+-- >>> replicateM @Maybe 3 Nothing+-- Nothing+--+-- >>> replicateM @Maybe 0 (Just "a")+-- Just Nothing+--+-- >>> replicateM @Maybe (-1) (Just "a")+-- Just Nothing+--+replicateM :: (Monad m, V.Unbox a) => Int -> m a -> m (Maybe (NonEmptyUVector a))+replicateM n a = fmap fromVector (V.replicateM n a)+{-# INLINE replicateM #-}++-- | /O(n)/ Execute the monadic action the given number of times and store+-- the results in a vector.+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+--+-- >>> replicate1M @Maybe 3 (Just "a")+-- Just ["a","a","a"]+--+-- >>> replicate1M @Maybe 3 Nothing+-- Nothing+--+-- >>> replicate1M @Maybe 0 (Just "a")+-- Just ["a"]+--+-- >>> replicate1M @Maybe (-1) (Just "a")+-- Just ["a"]+--+replicate1M :: (Monad m, V.Unbox a) => Int -> m a -> m (NonEmptyUVector a)+replicate1M n a = fmap unsafeFromVector (V.replicateM (max n 1) a)+{-# INLINE replicate1M #-}++-- | /O(n)/ Construct a 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'.+--+-- >>> generateM 3 (\i -> if i P.< 1 then ["a"] else ["b"])+-- [Just ["a","b","b"]]+--+-- >>> generateM @[] @Int 3 (const [])+-- []+--+-- >>> generateM @[] @Int 0 (const [1])+-- [Nothing]+--+-- >>> generateM @Maybe @Int (-1) (const Nothing)+-- Just Nothing+--+generateM :: (Monad m, V.Unbox a) => Int -> (Int -> m a) -> m (Maybe (NonEmptyUVector a))+generateM n f = fmap fromVector (V.generateM n f)+{-# INLINE generateM #-}++-- | /O(n)/ Construct a vector of the given length by applying the monadic+-- action to each index+--+-- This variant takes @max n 1@ for the supplied length parameter.+--+-- >>> generate1M 3 (\i -> if i P.< 1 then Just "a" else Just "b")+-- Just ["a","b","b"]+--+-- >>> generate1M 3 (const [])+-- []+--+-- >>> generate1M 0 (const $ Just 1)+-- Just [1]+--+-- >>> generate1M (-1) (const Nothing)+-- Nothing+--+generate1M :: (Monad m, V.Unbox a) => Int -> (Int -> m a) -> m (NonEmptyUVector a)+generate1M n f = fmap unsafeFromVector (V.generateM (max n 1) f)+{-# INLINE generate1M #-}++-- | /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'.+--+--+-- >>> iterateNM @Maybe 3 return "a"+-- Just (Just ["a","a","a"])+--+-- >>> iterateNM @Maybe 3 (const Nothing) "a"+-- Nothing+--+-- >>> iterateNM @Maybe 0 return "a"+-- Just Nothing+--+iterateNM :: (Monad m, V.Unbox a) => Int -> (a -> m a) -> a -> m (Maybe (NonEmptyUVector a))+iterateNM n f a = fmap fromVector (V.iterateNM n f a)+{-# INLINE iterateNM #-}++-- | /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.+--+--+-- >>> iterateN1M @Maybe 3 return "a"+-- Just ["a","a","a"]+--+-- >>> iterateN1M @Maybe 3 (const Nothing) "a"+-- Nothing+--+-- >>> iterateN1M @Maybe 0 return "a"+-- Just ["a"]+--+-- >>> iterateN1M @Maybe (-1) return "a"+-- Just ["a"]+--+iterateN1M :: (Monad m, V.Unbox a) => Int -> (a -> m a) -> a -> m (NonEmptyUVector a)+iterateN1M n f a = fmap unsafeFromVector (V.iterateNM (max n 1) f a)+{-# INLINE iterateN1M #-}++-- | Execute the monadic action and freeze the resulting non-empty vector.+--+create :: V.Unbox a => (forall s. ST s (MVector s a)) -> Maybe (NonEmptyUVector a)+create p = fromVector (G.create p)+{-# INLINE create #-}++-- | Execute the monadic action and freeze the resulting non-empty vector,+-- bypassing emptiness checks.+--+-- The onus is on the caller to guarantee the created vector is non-empty.+--+unsafeCreate :: V.Unbox a => (forall s. ST s (MVector s a)) -> NonEmptyUVector a+unsafeCreate p = unsafeFromVector (G.create p)+{-# INLINE unsafeCreate #-}++-- | Execute the monadic action and freeze the resulting non-empty vector.+--+createT+ :: (Traversable t, V.Unbox a)+ => (forall s. ST s (t (MVector s a)))+ -> t (Maybe (NonEmptyUVector a))+createT p = fmap fromVector (G.createT p)+{-# INLINE createT #-}++-- | Execute the monadic action and freeze the resulting non-empty vector.+--+-- The onus is on the caller to guarantee the created vector is non-empty.+--+unsafeCreateT+ :: (Traversable t, V.Unbox a)+ => (forall s. ST s (t (MVector s a)))+ -> t (NonEmptyUVector a)+unsafeCreateT p = fmap unsafeFromVector (G.createT p)+{-# INLINE unsafeCreateT #-}++-- ---------------------------------------------------------------------- --+-- Unfolding++-- | /O(n)/ Construct a non-empty 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 non-empty vector is returned.+--+--+-- >>> unfoldr (\b -> case b of "a" -> Just ("a", "b"); _ -> Nothing) "a"+-- Just ["a"]+--+-- >>> unfoldr (const Nothing) "a"+-- Nothing+--+unfoldr :: V.Unbox a => (b -> Maybe (a, b)) -> b -> Maybe (NonEmptyUVector a)+unfoldr f b = fromVector (V.unfoldr f b)+{-# INLINE unfoldr #-}++-- | /O(n)/ Construct a non-empty 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@.+--+--+-- >>> unfoldr1 (\b -> case b of "a" -> Just ("a", "b"); _ -> Nothing) "first" "a"+-- ["first","a"]+--+-- >>> unfoldr1 (const Nothing) "first" "a"+-- ["first"]+--+unfoldr1 :: V.Unbox a => (b -> Maybe (a, b)) -> a -> b -> NonEmptyUVector a+unfoldr1 f a b = cons a (unsafeFromVector (V.unfoldr f b))+{-# INLINE unfoldr1 #-}++-- | /O(n)/ Construct a 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 non-empty vector is returned.+--+--+-- >>> unfoldrN 3 (\b -> Just (b+1, b+1)) 0+-- Just [1,2,3]+--+-- >>> unfoldrN 3 (const Nothing) 0+-- Nothing+--+-- >>> unfoldrN 0 (\b -> Just (b+1, b+1)) 0+-- Nothing+--+unfoldrN :: V.Unbox a => Int -> (b -> Maybe (a, b)) -> b -> Maybe (NonEmptyUVector a)+unfoldrN n f b = fromVector (V.unfoldrN n f b)+{-# INLINE unfoldrN #-}++-- | /O(n)/ Construct a 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@.+--+--+-- >>> unfoldr1N 3 (\b -> Just (b+1, b+1)) 0 0+-- [0,1,2,3]+--+-- >>> unfoldr1N 3 (const Nothing) 0 0+-- [0]+--+-- >>> unfoldr1N 0 (\b -> Just (b+1, b+1)) 0 0+-- [0]+--+unfoldr1N+ :: V.Unbox a+ => Int+ -> (b -> Maybe (a, b))+ -> a+ -> b+ -> NonEmptyUVector a+unfoldr1N n f a b = cons a (unsafeFromVector (V.unfoldrN n f b))+{-# INLINE unfoldr1N #-}++-- | /O(n)/ Construct a non-empty 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 non-empty vector is returned.+--+unfoldrM+ :: (V.Unbox a, Monad m)+ => (b -> m (Maybe (a, b)))+ -> b+ -> m (Maybe (NonEmptyUVector a))+unfoldrM f b = fmap fromVector (V.unfoldrM f b)+{-# INLINE unfoldrM #-}++-- | /O(n)/ Construct a non-empty 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@.+--+unfoldr1M+ :: (Monad m, V.Unbox a)+ => (b -> m (Maybe (a, b)))+ -> a+ -> b+ -> m (NonEmptyUVector a)+unfoldr1M f a b = fmap (cons a . unsafeFromVector) (V.unfoldrM f b)+{-# INLINE unfoldr1M #-}++-- | /O(n)/ Construct a non-empty 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 non-empty vector is returned.+--+unfoldrNM+ :: (V.Unbox a, Monad m)+ => Int+ -> (b -> m (Maybe (a, b)))+ -> b+ -> m (Maybe (NonEmptyUVector a))+unfoldrNM n f b = fmap fromVector (V.unfoldrNM n f b)+{-# INLINE unfoldrNM #-}++-- | /O(n)/ Construct a non-empty 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@.+--+unfoldr1NM+ :: (V.Unbox a, Monad m)+ => Int+ -> (b -> m (Maybe (a, b)))+ -> a+ -> b+ -> m (NonEmptyUVector a)+unfoldr1NM n f a b = fmap (cons a . unsafeFromVector) (V.unfoldrNM n f b)+{-# INLINE unfoldr1NM #-}++-- | /O(n)/ Construct a non-empty 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 non-empty vector is returned.+--+constructN :: V.Unbox a => Int -> (Vector a -> a) -> Maybe (NonEmptyUVector a)+constructN n f = fromVector (V.constructN n f)+{-# INLINE constructN #-}++-- | /O(n)/ Construct a 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 non-empty vector is returned.+--+constructrN :: V.Unbox a => Int -> (Vector a -> a) -> Maybe (NonEmptyUVector a)+constructrN n f = fromVector (V.constructrN n f)+{-# INLINE constructrN #-}++-- ---------------------------------------------------------------------- --+-- Enumeration++-- | /O(n)/ Yield a non-emptyvector 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 non-empty vector.+--+enumFromN :: (V.Unbox a, Num a) => a -> Int -> Maybe (NonEmptyUVector a)+enumFromN a n = fromVector (V.enumFromN a n)+{-# INLINE enumFromN #-}++-- | /O(n)/ Yield a non-emptyvector of length @max n 1@ containing the+-- values x, x+1 etc. This operation is usually more efficient than+-- 'enumFromTo'.+--+enumFromN1 :: (V.Unbox a, Num a) => a -> Int -> NonEmptyUVector a+enumFromN1 a n = unsafeFromVector (V.enumFromN a (max n 1))+{-# INLINE enumFromN1 #-}++-- | /O(n)/ Yield a non-empty 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 non-empty vector.+--+enumFromStepN :: (V.Unbox a, Num a) => a -> a -> Int -> Maybe (NonEmptyUVector a)+enumFromStepN a0 a1 n = fromVector (V.enumFromStepN a0 a1 n)+{-# INLINE enumFromStepN #-}++-- | /O(n)/ Yield a non-empty vector of length @max n 1@ containing the+-- values x, x+y, x+y+y etc. This operations is usually more efficient than+-- 'enumFromThenTo'.+--+enumFromStepN1 :: (V.Unbox a, Num a) => a -> a -> Int -> NonEmptyUVector a+enumFromStepN1 a0 a1 n = unsafeFromVector (V.enumFromStepN a0 a1 (max n 1))+{-# INLINE enumFromStepN1 #-}++-- | /O(n)/ Enumerate values from x to y.+--+-- If an enumeration does not use meaningful indices, 'Nothing' is returned,+-- otherwise, 'Just' containing a non-empty vector.+--+-- /WARNING/: This operation can be very inefficient. If at all possible,+-- use 'enumFromN' instead.+--+--+enumFromTo :: (V.Unbox a, Enum a) => a -> a -> Maybe (NonEmptyUVector a)+enumFromTo a0 a1 = fromVector (V.enumFromTo a0 a1)+{-# INLINE enumFromTo #-}++-- | /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 non-empty vector.+--+-- /WARNING/: This operation can be very inefficient. If at all possible,+-- use 'enumFromStepN' instead.+enumFromThenTo :: (V.Unbox a, Enum a) => a -> a -> a -> Maybe (NonEmptyUVector a)+enumFromThenTo a0 a1 a2 = fromVector (V.enumFromThenTo a0 a1 a2)+{-# INLINE enumFromThenTo #-}++-- ---------------------------------------------------------------------- --+-- Concatenation++-- | /O(n)/ Prepend an element+--+-- >>> cons 1 (unsafeFromList [2,3])+-- [1,2,3]+--+cons :: V.Unbox a => a -> NonEmptyUVector a -> NonEmptyUVector a+cons a (NonEmptyUVector as) = consV a as+{-# INLINE cons #-}++-- | /O(n)/ Prepend an element to a Vector+--+-- >>> consV 1 (V.fromList [2,3])+-- [1,2,3]+--+consV :: V.Unbox a => a -> Vector a -> NonEmptyUVector a+consV a = NonEmptyUVector . V.cons a+{-# INLINE consV #-}++-- | /O(n)/ Append an element+--+-- >>> snoc (unsafeFromList [1,2]) 3+-- [1,2,3]+--+snoc :: V.Unbox a => NonEmptyUVector a -> a -> NonEmptyUVector a+snoc (NonEmptyUVector as) = snocV as+{-# INLINE snoc #-}++-- | /O(n)/ Append an element to a Vector+--+-- >>> snocV (V.fromList [1,2]) 3+-- [1,2,3]+--+snocV :: V.Unbox a => Vector a -> a -> NonEmptyUVector a+snocV as = NonEmptyUVector . V.snoc as+{-# INLINE snocV #-}++-- | /O(m+n)/ Concatenate two non-empty vectors+--+-- >>> (unsafeFromList [1..3]) ++ (unsafeFromList [4..6])+-- [1,2,3,4,5,6]+--+(++) :: V.Unbox a => NonEmptyUVector a -> NonEmptyUVector a -> NonEmptyUVector a+NonEmptyUVector v ++ NonEmptyUVector v' = NonEmptyUVector (v <> v')+{-# INLINE (++) #-}++-- | /O(n)/ Concatenate all non-empty vectors in the list+--+-- If list is empty, 'Nothing' is returned, otherwise 'Just'+-- containing the concatenated non-empty vectors+--+-- >>> concat [(unsafeFromList [1..3]), (unsafeFromList [4..6])]+-- Just [1,2,3,4,5,6]+--+concat :: V.Unbox a => [NonEmptyUVector a] -> Maybe (NonEmptyUVector a)+concat [] = Nothing+concat (a:as) = Just (concat1 (a :| as))+{-# INLINE concat #-}++-- | O(n) Concatenate all non-empty vectors in a non-empty list.+--+-- >>> concat1 ((unsafeFromList [1..3]) :| [(unsafeFromList [4..6])])+-- [1,2,3,4,5,6]+--+concat1 :: V.Unbox a => NonEmpty (NonEmptyUVector a) -> NonEmptyUVector a+concat1 = NonEmptyUVector . Foldable.foldl' go V.empty+ where+ go v (NonEmptyUVector a) = v <> a+{-# INLINE concat1 #-}++-- ---------------------------------------------------------------------- --+-- Conversions++-- | /O(n)/ Convert a non-empty vector to a non-empty list.+--+-- >>> toNonEmpty (unsafeFromList [1..3])+-- 1 :| [2,3]+--+toNonEmpty :: V.Unbox a => NonEmptyUVector a -> NonEmpty a+toNonEmpty = NonEmpty.fromList . V.toList . _neUvec+{-# INLINE toNonEmpty #-}++-- | O(n) Convert from a non-empty list to a non-empty vector.+--+-- >>> fromNonEmpty (1 :| [2,3])+-- [1,2,3]+--+fromNonEmpty :: V.Unbox a => NonEmpty a -> NonEmptyUVector a+fromNonEmpty = NonEmptyUVector . V.fromList . Foldable.toList+{-# INLINE fromNonEmpty #-}++-- | O(n) Convert from the first n-elements of a non-empty list to a+-- non-empty vector.+--+-- Returns 'Nothing' if indices are <= 0, otherwise 'Just' containing+-- the non-empty vector.+--+-- >>> fromNonEmptyN 3 (1 :| [2..5])+-- Just [1,2,3]+--+-- >>> fromNonEmptyN 0 (1 :| [2..5])+-- Nothing+--+fromNonEmptyN :: V.Unbox a => Int -> NonEmpty a -> Maybe (NonEmptyUVector a)+fromNonEmptyN n a = fromVector (V.fromListN n (Foldable.toList a))+{-# INLINE fromNonEmptyN #-}++-- | O(n) Convert from the first n-elements of a non-empty list to a+-- non-empty vector. This is a safe version of `fromNonEmptyN` which+-- takes @max n 1@ of the first n-elements of the non-empty list.+--+--+-- >>> fromNonEmptyN1 3 (1 :| [2..5])+-- [1,2,3]+--+-- >>> fromNonEmptyN1 0 (1 :| [2..5])+-- [1]+--+fromNonEmptyN1 :: V.Unbox a => Int -> NonEmpty a -> NonEmptyUVector a+fromNonEmptyN1 n = unsafeFromVector+ . V.fromListN (max n 1)+ . Foldable.toList+{-# INLINE fromNonEmptyN1 #-}++-- | /O(1)/ Convert from a non-empty vector to a vector.+--+--+-- >>> let nev :: NonEmptyUVector Int = unsafeFromList [1..3] in toVector nev+-- [1,2,3]+--+toVector :: V.Unbox a => NonEmptyUVector a -> Vector a+toVector = _neUvec+{-# INLINE toVector #-}++-- | /O(1)/ Convert from a vector to a non-empty vector.+--+-- If the vector is empty, then 'Nothing' is returned,+-- otherwise 'Just' containing the non-empty vector.+--+-- >>> fromVector $ V.fromList [1..3]+-- Just [1,2,3]+--+-- >>> fromVector $ V.fromList []+-- Nothing+--+fromVector :: V.Unbox a => Vector a -> Maybe (NonEmptyUVector a)+fromVector v = if V.null v then Nothing else Just (NonEmptyUVector v)+{-# INLINE fromVector #-}++-- | /O(1)/ Convert from a vector to a non-empty vector without+-- checking bounds.+--+-- /Warning/: the onus is on the user to ensure that their vector+-- is not empty, otherwise all bets are off!+--+--+-- >>> unsafeFromVector $ V.fromList [1..3]+-- [1,2,3]+--+unsafeFromVector :: V.Unbox a => Vector a -> NonEmptyUVector a+unsafeFromVector = NonEmptyUVector+{-# INLINE unsafeFromVector #-}++-- | /O(n)/ Convert from a non-empty vector to a list.+--+--+-- >>> let nev :: NonEmptyUVector Int = unsafeFromList [1..3] in toList nev+-- [1,2,3]+--+toList :: V.Unbox a => NonEmptyUVector a -> [a]+toList = V.toList . _neUvec+{-# INLINE toList #-}++-- | /O(n)/ Convert from a list to a non-empty vector.+--+--+-- >>> fromList [1..3]+-- Just [1,2,3]+--+-- >>> fromList []+-- Nothing+--+fromList :: V.Unbox a => [a] -> Maybe (NonEmptyUVector a)+fromList = fromVector . V.fromList+{-# INLINE fromList #-}++-- | /O(n)/ Convert from a list to a non-empty vector.+--+-- /Warning/: the onus is on the user to ensure that their vector+-- is not empty, otherwise all bets are off!+--+-- >>> unsafeFromList [1..3]+-- [1,2,3]+--+unsafeFromList :: V.Unbox a => [a] -> NonEmptyUVector a+unsafeFromList = unsafeFromVector . V.fromList+{-# INLINE unsafeFromList #-}++-- | /O(n)/ Convert the first n elements of a list to a non-empty vector.+--+-- If the list is empty or <= 0 elements are chosen, 'Nothing' is+-- returned, otherwise 'Just' containing the non-empty vector+--+-- >>> fromListN 3 [1..5]+-- Just [1,2,3]+--+-- >>> fromListN 3 []+-- Nothing+--+-- >>> fromListN 0 [1..5]+-- Nothing+--+fromListN :: V.Unbox a => Int -> [a] -> Maybe (NonEmptyUVector a)+fromListN n as = fromVector (V.fromListN n as)+{-# INLINE fromListN #-}++-- ---------------------------------------------------------------------- --+-- Restricting memory usage++-- | /O(n)/ Yield the argument but force it not to retain any extra memory,+-- possibly by copying it.+--+force :: V.Unbox a => NonEmptyUVector a -> NonEmptyUVector a+force (NonEmptyUVector a) = NonEmptyUVector (V.force a)+{-# INLINE force #-}++-- ---------------------------------------------------------------------- --+-- Bulk Updates++-- | /O(m+n)/ For each pair (i,a) from the list, replace the non-empty vector+-- element at position i by a.+--+-- >>> unsafeFromList [1..3] // [(2,4)]+-- [1,2,4]+--+-- >>> unsafeFromList [1..3] // []+-- [1,2,3]+--+(//) :: V.Unbox a => NonEmptyUVector a -> [(Int, a)] -> NonEmptyUVector a+NonEmptyUVector v // us = NonEmptyUVector (v V.// us)+{-# INLINE (//) #-}++-- | O(m+n) For each pair (i,a) from the vector of index/value pairs,+-- replace the vector element at position i by a.+--+-- >>> unsafeFromList [1..3] `update` V.fromList [(2,4)]+-- [1,2,4]+--+-- >>> unsafeFromList [1..3] `update` V.empty+-- [1,2,3]+--+update :: V.Unbox a => NonEmptyUVector a -> Vector (Int, a) -> NonEmptyUVector a+update (NonEmptyUVector v) v' = NonEmptyUVector (V.update v v')+{-# INLINE update #-}++-- | /O(m+min(n1,n2))/ For each index i from the index vector and the+-- corresponding value a from the value vector, replace the element of+-- the initial vector at position i by a.+--+--+-- >>> update_ (unsafeFromList [1..3]) (V.fromList [2]) (V.fromList [4])+-- [1,2,4]+--+-- >>> update_ (unsafeFromList [1..3]) V.empty V.empty+-- [1,2,3]+--+update_ :: V.Unbox a => NonEmptyUVector a -> Vector Int -> Vector a -> NonEmptyUVector a+update_ (NonEmptyUVector v) is as = NonEmptyUVector (V.update_ v is as)+{-# INLINE update_ #-}++-- | Same as '(//)' but without bounds checking.+--+unsafeUpd :: V.Unbox a => NonEmptyUVector a -> [(Int, a)] -> NonEmptyUVector a+unsafeUpd (NonEmptyUVector v) us = NonEmptyUVector (V.unsafeUpd v us)+{-# INLINE unsafeUpd #-}++-- | Same as 'update' but without bounds checking.+--+unsafeUpdate :: V.Unbox a => NonEmptyUVector a -> Vector (Int, a) -> NonEmptyUVector a+unsafeUpdate (NonEmptyUVector v) us = NonEmptyUVector (V.unsafeUpdate v us)+{-# INLINE unsafeUpdate #-}++-- | Same as 'update_' but without bounds checking.+--+unsafeUpdate_ :: V.Unbox a => NonEmptyUVector a -> Vector Int -> Vector a -> NonEmptyUVector a+unsafeUpdate_ (NonEmptyUVector v) is as = NonEmptyUVector (V.unsafeUpdate_ v is as)+{-# INLINE unsafeUpdate_ #-}++-- ---------------------------------------------------------------------- --+-- Accumulation++-- | /O(m+n)/ For each pair @(i,b)@ from the non-empty list, replace the+-- non-empty vector element @a@ at position @i@ by @f a b@.+--+--+-- >>> accum (+) (unsafeFromList [1..3]) [(2,10)]+-- [1,2,13]+--+-- >>> accum (+) (unsafeFromList [1..3]) []+-- [1,2,3]+--+accum+ :: (V.Unbox a, V.Unbox b)+ => (a -> b -> a)+ -- ^ accumulating function @f@+ -> NonEmptyUVector a+ -- ^ initial non-empty vector (of length @m@)+ -> [(Int, b)]+ -- ^ list of index/value pairs (of length @n@)+ -> NonEmptyUVector a+accum f (NonEmptyUVector v) u = NonEmptyUVector (V.accum f v u)+{-# INLINE accum #-}++-- | /O(m+n)/ For each pair @(i,b)@ from the vector of pairs, replace the+-- non-empty vector element @a@ at position @i@ by @f a b@.+--+-- >>> accumulate (+) (unsafeFromList [1..3]) (V.fromList [(2,10)])+-- [1,2,13]+--+-- >>> accumulate (+) (unsafeFromList [1..3]) V.empty+-- [1,2,3]+--+accumulate+ :: (V.Unbox a, V.Unbox b)+ => (a -> b -> a)+ -- ^ accumulating function @f@+ -> NonEmptyUVector a+ -- ^ initial non-empty vector (of length @m@)+ -> Vector (Int, b)+ -- ^ vector of index/value pairs (of length @n@)+ -> NonEmptyUVector a+accumulate f (NonEmptyUVector v) u = NonEmptyUVector (V.accumulate f v u)+{-# INLINE accumulate #-}++-- | /O(m+min(n1,n2))/ For each index @i@ from the index vector and the+-- corresponding value @b@ from the the value vector, replace the element+-- of the initial non-empty vector at position @i@ by @f a b@.+--+-- >>> accumulate_ (+) (unsafeFromList [1..3]) (V.fromList [2]) (V.fromList [10])+-- [1,2,13]+--+-- >>> accumulate_ (+) (unsafeFromList [1..3]) V.empty V.empty+-- [1,2,3]+--+accumulate_+ :: (V.Unbox a, V.Unbox b)+ => (a -> b -> a)+ -- ^ accumulating function @f@+ -> NonEmptyUVector a+ -- ^ initial non-empty vector (of length @m@)+ -> Vector Int+ -- ^ vector of indices (of length @n1@)+ -> Vector b+ -- ^ vector of values (of length @n2@)+ -> NonEmptyUVector a+accumulate_ f (NonEmptyUVector v) i b = NonEmptyUVector (V.accumulate_ f v i b)+{-# INLINE accumulate_ #-}++-- | Same as 'accum' but without bounds checking.+--+unsafeAccum+ :: (V.Unbox a, V.Unbox b)+ => (a -> b -> a)+ -- ^ accumulating function @f@+ -> NonEmptyUVector a+ -- ^ initial non-empty vector (of length @m@)+ -> [(Int, b)]+ -- ^ list of index/value pairs (of length @n@)+ -> NonEmptyUVector a+unsafeAccum f (NonEmptyUVector v) u = NonEmptyUVector (V.unsafeAccum f v u)+{-# INLINE unsafeAccum #-}++-- | Same as 'accumulate' but without bounds checking.+--+unsafeAccumulate+ :: (V.Unbox a, V.Unbox b) + => (a -> b -> a)+ -- ^ accumulating function @f@+ -> NonEmptyUVector a+ -- ^ initial non-empty vector (of length @m@)+ -> Vector (Int, b)+ -- ^ vector of index/value pairs (of length @n@)+ -> NonEmptyUVector a+unsafeAccumulate f v u = NonEmptyUVector (V.unsafeAccumulate f v' u)+ where+ v' = _neUvec v+{-# INLINE unsafeAccumulate #-}++-- | Same as 'accumulate_' but without bounds checking.+--+unsafeAccumulate_+ :: (V.Unbox a, V.Unbox b)+ => (a -> b -> a)+ -- ^ accumulating function @f@+ -> NonEmptyUVector a+ -- ^ initial non-empty vector (of length @m@)+ -> Vector Int+ -- ^ vector of indices of length @n1@+ -> Vector b+ -- ^ vector of values (of length @n2@)+ -> NonEmptyUVector a+unsafeAccumulate_ f v i b = NonEmptyUVector (V.unsafeAccumulate_ f v' i b)+ where+ v' = _neUvec v+{-# INLINE unsafeAccumulate_ #-}++-- ---------------------------------------------------------------------- --+-- Permutations++-- | /O(n)/ Reverse a non-empty vector+--+-- >>> reverse $ unsafeFromList [1..3]+-- [3,2,1]+--+reverse :: V.Unbox a => NonEmptyUVector a -> NonEmptyUVector a+reverse = NonEmptyUVector . V.reverse . _neUvec+{-# INLINE reverse #-}++-- | /O(n)/ Yield the non-empty vector obtained by replacing each element+-- @i@ of the non-empty index vector by @xs'!'i@. This is equivalent to+-- @'map' (xs'!') is@ but is often much more efficient.+--+-- >>> backpermute (unsafeFromList [1..3]) (unsafeFromList [2,0])+-- [3,1]+--+backpermute :: V.Unbox a => NonEmptyUVector a -> NonEmptyUVector Int -> NonEmptyUVector a+backpermute (NonEmptyUVector v) (NonEmptyUVector i)+ = NonEmptyUVector (V.backpermute v i)+{-# INLINE backpermute #-}++-- | Same as 'backpermute' but without bounds checking.+--+unsafeBackpermute+ :: V.Unbox a+ => NonEmptyUVector a+ -> NonEmptyUVector Int+ -> NonEmptyUVector a+unsafeBackpermute (NonEmptyUVector v) (NonEmptyUVector i)+ = NonEmptyUVector (V.unsafeBackpermute v i)+{-# INLINE unsafeBackpermute #-}++-- ---------------------------------------------------------------------- --+-- Safe destructive updates++-- | Apply a destructive operation to a non-empty vector. The operation+-- will be performed in place if it is safe to do so and will modify a+-- copy of the non-empty vector otherwise.+--+modify+ :: V.Unbox a+ => (forall s. MVector s a -> ST s ())+ -> NonEmptyUVector a+ -> NonEmptyUVector a+modify p (NonEmptyUVector v) = NonEmptyUVector (V.modify p v)+{-# INLINE modify #-}++-- ---------------------------------------------------------------------- --+-- Indexing++-- | /O(n)/ Pair each element in a vector with its index.+--+-- >>> indexed $ unsafeFromList ["a","b","c"]+-- [(0,"a"),(1,"b"),(2,"c")]+--+indexed :: (V.Unbox a) => NonEmptyUVector a -> NonEmptyUVector (Int, a)+indexed = NonEmptyUVector . V.indexed . _neUvec+{-# INLINE indexed #-}++-- ---------------------------------------------------------------------- --+-- Mapping++-- | /O(n)/ Map a function over a non-empty vector.+--+-- >>> map (+1) $ unsafeFromList [1..3]+-- [2,3,4]+--+map :: (V.Unbox a, V.Unbox b) => (a -> b) -> NonEmptyUVector a -> NonEmptyUVector b+map f = NonEmptyUVector . V.map f . _neUvec+{-# INLINE map #-}++-- | /O(n)/ Apply a function to every element of a non-empty vector and+-- its index.+--+-- >>> imap (\i a -> if i == 2 then a+1 else a+0) $ unsafeFromList [1..3]+-- [1,2,4]+--+imap :: (V.Unbox a, V.Unbox b) => (Int -> a -> b) -> NonEmptyUVector a -> NonEmptyUVector b+imap f = NonEmptyUVector . V.imap f . _neUvec+{-# INLINE imap #-}++-- | Map a function over a vector and concatenate the results.+--+-- >>> concatMap (\a -> unsafeFromList [a,a]) (unsafeFromList [1,2,3])+-- [1,1,2,2,3,3]+--+concatMap+ :: (V.Unbox a, V.Unbox b)+ => (a -> NonEmptyUVector b)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+concatMap f = NonEmptyUVector . V.concatMap (_neUvec . f) . _neUvec+{-# INLINE concatMap #-}++-- ---------------------------------------------------------------------- --+-- Monadic Mapping++-- | /O(n)/ Apply the monadic action to all elements of the non-empty+-- vector, yielding non-empty vector of results.+--+-- >>> mapM Just (unsafeFromList [1..3])+-- Just [1,2,3]+--+-- >>> mapM (const Nothing) (unsafeFromList [1..3])+-- Nothing+--+mapM :: (V.Unbox a, V.Unbox b, Monad m) => (a -> m b) -> NonEmptyUVector a -> m (NonEmptyUVector b)+mapM f = fmap NonEmptyUVector . V.mapM f . _neUvec+{-# INLINE mapM #-}++-- | /O(n)/ Apply the monadic action to every element of a non-empty+-- vector and its index, yielding a non-empty vector of results.+--+-- >>> imapM (\i a -> if i == 1 then Just a else Just 0) (unsafeFromList [1..3])+-- Just [0,2,0]+--+-- >>> imapM (\_ _ -> Nothing) (unsafeFromList [1..3])+-- Nothing+--+imapM+ :: (V.Unbox a, V.Unbox b, Monad m)+ => (Int -> a -> m b)+ -> NonEmptyUVector a+ -> m (NonEmptyUVector b)+imapM f = fmap NonEmptyUVector . V.imapM f . _neUvec+{-# INLINE imapM #-}++-- | /O(n)/ Apply the monadic action to all elements of a non-empty vector+-- and ignore the results.+--+-- >>> mapM_ (const $ Just ()) (unsafeFromList [1..3])+-- Just ()+--+-- >>> mapM_ (const Nothing) (unsafeFromList [1..3])+-- Nothing+--+mapM_ :: (V.Unbox a, Monad m) => (a -> m b) -> NonEmptyUVector a -> m ()+mapM_ f = V.mapM_ f . _neUvec+{-# INLINE mapM_ #-}++-- | /O(n)/ Apply the monadic action to every element of a non-emptpy+-- vector and its index, ignoring the results+--+-- >>> imapM_ (\i a -> if i == 1 then P.print a else P.putStrLn "0") (unsafeFromList [1..3])+-- 0+-- 2+-- 0+--+-- >>> imapM_ (\_ _ -> Nothing) (unsafeFromList [1..3])+-- Nothing+--+imapM_ :: (V.Unbox a, Monad m) => (Int -> a -> m b) -> NonEmptyUVector a -> m ()+imapM_ f = V.imapM_ f . _neUvec+{-# INLINE imapM_ #-}++-- | /O(n)/ Apply the monadic action to all elements of the non-empty+-- vector, yielding a non0empty vector of results.+--+-- Equivalent to @flip 'mapM'@.+--+forM :: (V.Unbox a, V.Unbox b, Monad m) => NonEmptyUVector a -> (a -> m b) -> m (NonEmptyUVector b)+forM (NonEmptyUVector v) f = fmap NonEmptyUVector (V.forM v f)+{-# INLINE forM #-}++-- | /O(n)/ Apply the monadic action to all elements of a non-empty+-- vector and ignore the results.+--+-- Equivalent to @flip 'mapM_'@.+--+forM_ :: (V.Unbox a, Monad m) => NonEmptyUVector a -> (a -> m b) -> m ()+forM_ (NonEmptyUVector v) f = V.forM_ v f+{-# INLINE forM_ #-}++-- ---------------------------------------------------------------------- --+-- Zipping++-- | /O(min(m,n))/ Zip two non-empty vectors with the given function.+--+-- >>> zipWith (+) (unsafeFromList [1..3]) (unsafeFromList [1..3])+-- [2,4,6]+--+zipWith+ :: (V.Unbox a, V.Unbox b, V.Unbox c)+ => (a -> b -> c)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+zipWith f a b = NonEmptyUVector (V.zipWith f a' b')+ where+ a' = _neUvec a+ b' = _neUvec b+{-# INLINE zipWith #-}++-- | Zip three non-empty vectors with the given function.+--+--+zipWith3+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d)+ => (a -> b -> c -> d)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector d+zipWith3 f a b c = NonEmptyUVector (V.zipWith3 f a' b' c')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+{-# INLINE zipWith3 #-}++-- | Zip four non-empty vectors with the given function.+--+zipWith4+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d, V.Unbox e)+ => (a -> b -> c -> d -> e)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector d+ -> NonEmptyUVector e+zipWith4 f a b c d = NonEmptyUVector (V.zipWith4 f a' b' c' d')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+ d' = _neUvec d+{-# INLINE zipWith4 #-}++-- | Zip five non-empty vectors with the given function.+--+zipWith5+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d, V.Unbox e, V.Unbox f)+ => (a -> b -> c -> d -> e -> f)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector d+ -> NonEmptyUVector e+ -> NonEmptyUVector f+zipWith5 f a b c d e = NonEmptyUVector (V.zipWith5 f a' b' c' d' e')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+ d' = _neUvec d+ e' = _neUvec e+{-# INLINE zipWith5 #-}++-- | Zip six non-empty vectors with the given function.+--+zipWith6+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d, V.Unbox e, V.Unbox f, V.Unbox g)+ => (a -> b -> c -> d -> e -> f -> g)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector d+ -> NonEmptyUVector e+ -> NonEmptyUVector f+ -> NonEmptyUVector g+zipWith6 k a b c d e f = NonEmptyUVector (V.zipWith6 k a' b' c' d' e' f')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+ d' = _neUvec d+ e' = _neUvec e+ f' = _neUvec f+{-# INLINE zipWith6 #-}+++-- | /O(min(m,n))/ Zip two non-empty vectors with a function that also+-- takes the elements' indices.+--+izipWith+ :: (V.Unbox a, V.Unbox b, V.Unbox c)+ => (Int -> a -> b -> c)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+izipWith f a b = NonEmptyUVector (V.izipWith f a' b')+ where+ a' = _neUvec a+ b' = _neUvec b+{-# INLINE izipWith #-}++-- | Zip three non-empty vectors and their indices with the given function.+--+izipWith3+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d)+ => (Int -> a -> b -> c -> d)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector d+izipWith3 f a b c = NonEmptyUVector (V.izipWith3 f a' b' c')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+{-# INLINE izipWith3 #-}++-- | Zip four non-empty vectors and their indices with the given function.+--+izipWith4+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d, V.Unbox e)+ => (Int -> a -> b -> c -> d -> e)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector d+ -> NonEmptyUVector e+izipWith4 f a b c d = NonEmptyUVector (V.izipWith4 f a' b' c' d')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+ d' = _neUvec d+{-# INLINE izipWith4 #-}++-- | Zip five non-empty vectors and their indices with the given function.+--+izipWith5+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d, V.Unbox e, V.Unbox f)+ => (Int -> a -> b -> c -> d -> e -> f)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector d+ -> NonEmptyUVector e+ -> NonEmptyUVector f+izipWith5 f a b c d e = NonEmptyUVector (V.izipWith5 f a' b' c' d' e')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+ d' = _neUvec d+ e' = _neUvec e+{-# INLINE izipWith5 #-}++-- | Zip six non-empty vectors and their indices with the given function.+--+izipWith6+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d, V.Unbox e, V.Unbox f, V.Unbox g)+ => (Int -> a -> b -> c -> d -> e -> f -> g)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector d+ -> NonEmptyUVector e+ -> NonEmptyUVector f+ -> NonEmptyUVector g+izipWith6 k a b c d e f = NonEmptyUVector (V.izipWith6 k a' b' c' d' e' f')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+ d' = _neUvec d+ e' = _neUvec e+ f' = _neUvec f+{-# INLINE izipWith6 #-}++-- | /O(min(n,m))/ Elementwise pairing of non-empty vector elements. This is a special case+-- of 'zipWith' where the function argument is @(,)@+--+zip :: (V.Unbox a, V.Unbox b) => NonEmptyUVector a -> NonEmptyUVector b -> NonEmptyUVector (a, b)+zip a b = NonEmptyUVector (V.zip a' b')+ where+ a' = _neUvec a+ b' = _neUvec b+{-# INLINE zip #-}++-- | Zip together three non-empty vectors.+--+zip3+ :: (V.Unbox a, V.Unbox b, V.Unbox c)+ => NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector (a, b, c)+zip3 a b c = NonEmptyUVector (V.zip3 a' b' c')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+{-# INLINE zip3 #-}++-- | Zip together four non-empty vectors.+--+zip4+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d)+ => NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector d+ -> NonEmptyUVector (a, b, c, d)+zip4 a b c d = NonEmptyUVector (V.zip4 a' b' c' d')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+ d' = _neUvec d+{-# INLINE zip4 #-}++-- | Zip together five non-empty vectors.+--+zip5+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d, V.Unbox e)+ => NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector d+ -> NonEmptyUVector e+ -> NonEmptyUVector (a, b, c, d, e)+zip5 a b c d e = NonEmptyUVector (V.zip5 a' b' c' d' e')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+ d' = _neUvec d+ e' = _neUvec e+{-# INLINE zip5 #-}++-- | Zip together six non-empty vectors.+--+zip6+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d, V.Unbox e, V.Unbox f)+ => NonEmptyUVector a+ -> NonEmptyUVector b+ -> NonEmptyUVector c+ -> NonEmptyUVector d+ -> NonEmptyUVector e+ -> NonEmptyUVector f+ -> NonEmptyUVector (a, b, c, d, e, f)+zip6 a b c d e f = NonEmptyUVector (V.zip6 a' b' c' d' e' f')+ where+ a' = _neUvec a+ b' = _neUvec b+ c' = _neUvec c+ d' = _neUvec d+ e' = _neUvec e+ f' = _neUvec f+{-# INLINE zip6 #-}++-- ---------------------------------------------------------------------- --+-- Monadic Zipping++-- | /O(min(m,n))/ Zip the two non-empty vectors with the monadic action+-- and yield a non-empty vector of results.+--+zipWithM+ :: (V.Unbox a, V.Unbox b, V.Unbox c, Monad m)+ => (a -> b -> m c)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> m (NonEmptyUVector c)+zipWithM f a b = fmap NonEmptyUVector (V.zipWithM f a' b')+ where+ a' = _neUvec a+ b' = _neUvec b+{-# INLINE zipWithM #-}++-- | /O(min(m,n))/ Zip the two non-empty vectors with a monadic action+-- that also takes the element index and yield a vector of results.+--+izipWithM+ :: (V.Unbox a, V.Unbox b, V.Unbox c, Monad m)+ => (Int -> a -> b -> m c)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> m (NonEmptyUVector c)+izipWithM f a b = fmap NonEmptyUVector (V.izipWithM f a' b')+ where+ a' = _neUvec a+ b' = _neUvec b+{-# INLINE izipWithM #-}++-- | /O(min(m,n))/ Zip the two non-empty vectors with the monadic action+-- and ignore the results.+--+zipWithM_+ :: (V.Unbox a, V.Unbox b, Monad m)+ => (a -> b -> m c)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> m ()+zipWithM_ f a b = V.zipWithM_ f (_neUvec a) (_neUvec b)+{-# INLINE zipWithM_ #-}++-- | /O(min(m,n))/ Zip the two non-empty vectors with a monadic action+-- that also takes the element index and ignore the results.+--+izipWithM_+ :: (V.Unbox a, V.Unbox b, Monad m)+ => (Int -> a -> b -> m c)+ -> NonEmptyUVector a+ -> NonEmptyUVector b+ -> m ()+izipWithM_ f a b = V.izipWithM_ f (_neUvec a) (_neUvec b)+{-# INLINE izipWithM_ #-}++-- ---------------------------------------------------------------------- --+-- Unzipping++-- | /O(min(m,n))/ Unzip a non-empty vector of pairs.+--+unzip :: (V.Unbox a, V.Unbox b) => NonEmptyUVector (a, b) -> (NonEmptyUVector a, NonEmptyUVector b)+unzip (NonEmptyUVector v) = case V.unzip v of+ ~(a,b) -> (NonEmptyUVector a, NonEmptyUVector b)+{-# INLINE unzip #-}++-- | Unzip a non-empty vector of triples.+--+unzip3+ :: (V.Unbox a, V.Unbox b, V.Unbox c) + => NonEmptyUVector (a, b, c)+ -> (NonEmptyUVector a, NonEmptyUVector b, NonEmptyUVector c)+unzip3 (NonEmptyUVector v) = case V.unzip3 v of+ ~(a,b,c) ->+ ( NonEmptyUVector a+ , NonEmptyUVector b+ , NonEmptyUVector c+ )+{-# INLINE unzip3 #-}++-- | Unzip a non-empty vector of quadruples.+--+unzip4+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d) + => NonEmptyUVector (a, b, c, d)+ -> ( NonEmptyUVector a+ , NonEmptyUVector b+ , NonEmptyUVector c+ , NonEmptyUVector d+ )+unzip4 (NonEmptyUVector v) = case V.unzip4 v of+ ~(a,b,c,d) ->+ ( NonEmptyUVector a+ , NonEmptyUVector b+ , NonEmptyUVector c+ , NonEmptyUVector d+ )+{-# INLINE unzip4 #-}++-- | Unzip a non-empty vector of quintuples.+--+unzip5+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d, V.Unbox e) + => NonEmptyUVector (a, b, c, d, e)+ -> ( NonEmptyUVector a+ , NonEmptyUVector b+ , NonEmptyUVector c+ , NonEmptyUVector d+ , NonEmptyUVector e+ )+unzip5 (NonEmptyUVector v) = case V.unzip5 v of+ ~(a,b,c,d,e) ->+ ( NonEmptyUVector a+ , NonEmptyUVector b+ , NonEmptyUVector c+ , NonEmptyUVector d+ , NonEmptyUVector e+ )+{-# INLINE unzip5 #-}++-- | Unzip a non-empty vector of sextuples.+--+unzip6+ :: (V.Unbox a, V.Unbox b, V.Unbox c, V.Unbox d, V.Unbox e, V.Unbox f) + => NonEmptyUVector (a, b, c, d, e, f)+ -> ( NonEmptyUVector a+ , NonEmptyUVector b+ , NonEmptyUVector c+ , NonEmptyUVector d+ , NonEmptyUVector e+ , NonEmptyUVector f+ )+unzip6 (NonEmptyUVector v) = case V.unzip6 v of+ ~(a,b,c,d,e,f) ->+ ( NonEmptyUVector a+ , NonEmptyUVector b+ , NonEmptyUVector c+ , NonEmptyUVector d+ , NonEmptyUVector e+ , NonEmptyUVector f+ )+{-# INLINE unzip6 #-}++-- ---------------------------------------------------------------------- --+-- Filtering++-- | /O(n)/ Drop elements that do not satisfy the predicate.+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+-- >>> filter (\a -> if a == 2 then False else True) (unsafeFromList [1..3])+-- [1,3]+--+-- >>> filter (const False) (unsafeFromList [1..3])+-- []+--+filter :: V.Unbox a => (a -> Bool) -> NonEmptyUVector a -> Vector a+filter f = V.filter f . _neUvec+{-# INLINE filter #-}++-- | /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.+--+-- >>> ifilter (\i a -> if a == 2 || i == 0 then False else True) (unsafeFromList [1..3])+-- [3]+--+-- >>> ifilter (\_ _ -> False) (unsafeFromList [1..3])+-- []+--+ifilter+ :: V.Unbox a+ => (Int -> a -> Bool)+ -> NonEmptyUVector a+ -> Vector a+ifilter f = V.ifilter f . _neUvec+{-# INLINE ifilter #-}++-- | /O(n)/ Drop elements that do not satisfy the monadic predicate.+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+-- >>> 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+ :: (V.Unbox a, Monad m)+ => (a -> m Bool)+ -> NonEmptyUVector a+ -> m (Vector a)+filterM f = V.filterM f . _neUvec+{-# INLINE filterM #-}++-- | /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.+--+-- TODO: this should be a more efficient function in @vector@.+--+-- >>> 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+ :: (V.Unbox a, Monad m)+ => (Int -> a -> m Bool)+ -> NonEmptyUVector a+ -> m (Vector a)+ifilterM f = fmap (V.map snd)+ . V.filterM (uncurry f)+ . V.indexed+ . _neUvec+{-# INLINE ifilterM #-}++-- | /O(n)/ Drop repeated adjacent elements.+--+-- >>> uniq $ unsafeFromList [1,1,2,2,3,3,1]+-- [1,2,3,1]+--+uniq :: (V.Unbox a, Eq a) => NonEmptyUVector a -> NonEmptyUVector a+uniq = NonEmptyUVector . V.uniq . _neUvec+{-# INLINE uniq #-}++-- | /O(n)/ Drop elements when predicate returns Nothing+--+-- If no elements satisfy the predicate, the resulting vector may be empty.+--+-- >>> mapMaybe (\a -> if a == 2 then Nothing else Just a) (unsafeFromList [1..3])+-- [1,3]+--+mapMaybe+ :: (V.Unbox a, V.Unbox b)+ => (a -> Maybe b)+ -> NonEmptyUVector a+ -> Vector b+mapMaybe f = V.mapMaybe f . _neUvec+{-# INLINE mapMaybe #-}++-- | /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.+--+-- >>> imapMaybe (\i a -> if a == 2 || i == 2 then Nothing else Just a) (unsafeFromList [1..3])+-- [1]+--+imapMaybe+ :: (V.Unbox a, V.Unbox b) + => (Int -> a -> Maybe b)+ -> NonEmptyUVector a+ -> Vector b+imapMaybe f = V.imapMaybe f . _neUvec+{-# INLINE imapMaybe #-}++-- | /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.+--+-- >>> takeWhile (/= 3) (unsafeFromList [1..3])+-- [1,2]+--+takeWhile :: V.Unbox a => (a -> Bool) -> NonEmptyUVector a -> Vector a+takeWhile f = V.takeWhile f . _neUvec+{-# INLINE takeWhile #-}++-- | /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.+--+-- >>> dropWhile (/= 3) (unsafeFromList [1..3])+-- [3]+--+dropWhile :: V.Unbox a => (a -> Bool) -> NonEmptyUVector a -> Vector a+dropWhile f = V.dropWhile f . _neUvec+{-# INLINE dropWhile #-}++-- ---------------------------------------------------------------------- --+-- Partitioning++-- | /O(n)/ Split the non-empty 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.+--+-- >>> partition (< 3) (unsafeFromList [1..5])+-- ([1,2],[3,4,5])+--+partition :: V.Unbox a => (a -> Bool) -> NonEmptyUVector a -> (Vector a, Vector a)+partition f = V.partition f . _neUvec+{-# INLINE partition #-}++-- | /O(n)/ Split the non-empty vector in two parts, the first one+-- containing the Left elements and the second containing the+-- Right elements. The relative order of the elements is preserved.+--+-- If all elements produce a Left (or Right), one of the+-- resulting vectors may be empty.+--+-- >>> partitionWith (\a -> if a < 3 then Left a else Right (P.show a)) (unsafeFromList [1..5])+-- ([1,2],["3","4","5"])+--+partitionWith :: (V.Unbox a, V.Unbox b, V.Unbox c) => + (a -> Either b c) -> NonEmptyUVector a -> (Vector b, Vector c)+partitionWith f = V.partitionWith f . _neUvec+{-# INLINE partitionWith #-}++-- | /O(n)/ Split the non-empty 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.+--+unstablePartition+ :: V.Unbox a+ => (a -> Bool)+ -> NonEmptyUVector a+ -> (Vector a, Vector a)+unstablePartition f = V.unstablePartition f . _neUvec+{-# INLINE unstablePartition #-}++-- | /O(n)/ Split the non-empty 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.+--+-- >>> span (== 1) (unsafeFromList [1,1,2,3,1])+-- ([1,1],[2,3,1])+--+span :: V.Unbox a => (a -> Bool) -> NonEmptyUVector a -> (Vector a, Vector a)+span f = V.span f . _neUvec+{-# INLINE span #-}++-- | /O(n)/ Split the 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.+--+-- >>> break (== 2) (unsafeFromList [1,1,2,3,1])+-- ([1,1],[2,3,1])+--+break :: V.Unbox a => (a -> Bool) -> NonEmptyUVector a -> (Vector a, Vector a)+break f = V.break f . _neUvec+{-# INLINE break #-}++-- ---------------------------------------------------------------------- --+-- Searching++-- | /O(n)/ Check if the non-empty vector contains an element+--+-- >>> elem 1 $ unsafeFromList [1..3]+-- True+-- >>> elem 4 $ unsafeFromList [1..3]+-- False+--+elem :: (V.Unbox a, Eq a) => a -> NonEmptyUVector a -> Bool+elem a = V.elem a . _neUvec+{-# INLINE elem #-}++-- | /O(n)/ Check if the non-empty vector does not contain an element+-- (inverse of 'elem')+--+-- >>> notElem 1 $ unsafeFromList [1..3]+-- False+--+-- >>> notElem 4 $ unsafeFromList [1..3]+-- True+--+notElem :: (V.Unbox a, Eq a) => a -> NonEmptyUVector a -> Bool+notElem a = V.notElem a . _neUvec+{-# INLINE notElem #-}++-- | /O(n)/ Yield 'Just' the first element matching the predicate or+-- 'Nothing' if no such element exists.+--+-- >>> find (< 2) $ unsafeFromList [1..3]+-- Just 1+--+-- >>> find (< 0) $ unsafeFromList [1..3]+-- Nothing+--+find :: V.Unbox a => (a -> Bool) -> NonEmptyUVector a -> Maybe a+find f = V.find f . _neUvec+{-# INLINE find #-}++-- | /O(n)/ Yield 'Just' the index of the first element matching the+-- predicate or 'Nothing' if no such element exists.+--+-- >>> findIndex (< 2) $ unsafeFromList [1..3]+-- Just 0+--+-- >>> findIndex (< 0) $ unsafeFromList [1..3]+-- Nothing+--+findIndex :: V.Unbox a => (a -> Bool) -> NonEmptyUVector a -> Maybe Int+findIndex f = V.findIndex f . _neUvec+{-# INLINE findIndex #-}++-- | /O(n)/ Yield the indices of elements satisfying the predicate in+-- ascending order.+--+-- >>> findIndices (< 3) $ unsafeFromList [1..3]+-- [0,1]+--+-- >>> findIndices (< 0) $ unsafeFromList [1..3]+-- []+--+findIndices :: V.Unbox a => (a -> Bool) -> NonEmptyUVector a -> Vector Int+findIndices f = V.findIndices f . _neUvec+{-# INLINE findIndices #-}++-- | /O(n)/ Yield 'Just' the index of the first occurence of the given+-- element or 'Nothing' if the non-empty vector does not contain the+-- element. This is a specialised version of 'findIndex'.+--+-- >>> elemIndex 1 $ unsafeFromList [1..3]+-- Just 0+--+-- >>> elemIndex 0 $ unsafeFromList [1..3]+-- Nothing+--+elemIndex :: (V.Unbox a, Eq a) => a -> NonEmptyUVector a -> Maybe Int+elemIndex a = V.elemIndex a . _neUvec+{-# INLINE elemIndex #-}++-- | /O(n)/ Yield the indices of all occurences of the given element in+-- ascending order. This is a specialised version of 'findIndices'.+--+-- >>> elemIndices 1 $ unsafeFromList [1,2,3,1]+-- [0,3]+--+-- >>> elemIndices 0 $ unsafeFromList [1..3]+-- []+--+elemIndices :: (V.Unbox a, Eq a) => a -> NonEmptyUVector a -> Vector Int+elemIndices a = V.elemIndices a . _neUvec+{-# INLINE elemIndices #-}++-- ---------------------------------------------------------------------- --+-- Folding++-- | /O(n)/ Left monoidal fold+--+foldl :: V.Unbox b => (a -> b -> a) -> a -> NonEmptyUVector b -> a+foldl f a = V.foldl f a . _neUvec+{-# INLINE foldl #-}++-- | /O(n)/ Left semigroupal fold+--+foldl1 :: V.Unbox a => (a -> a -> a) -> NonEmptyUVector a -> a+foldl1 f = V.foldl1 f . _neUvec+{-# INLINE foldl1 #-}++-- | /O(n)/ Strict Left monoidal fold+--+foldl' :: V.Unbox b => (a -> b -> a) -> a -> NonEmptyUVector b -> a+foldl' f a = V.foldl' f a . _neUvec+{-# INLINE foldl' #-}++-- | /O(n)/ Strict Left semigroupal fold+--+foldl1' :: V.Unbox a => (a -> a -> a) -> NonEmptyUVector a -> a+foldl1' f = V.foldl1' f . _neUvec+{-# INLINE foldl1' #-}++-- | /O(n)/ Right monoidal fold+--+foldr :: V.Unbox a => (a -> b -> b) -> b -> NonEmptyUVector a -> b+foldr f b = V.foldr f b . _neUvec+{-# INLINE foldr #-}++-- | /O(n)/ Right semigroupal fold+--+foldr1 :: V.Unbox a => (a -> a -> a) -> NonEmptyUVector a -> a+foldr1 f = V.foldr1 f . _neUvec+{-# INLINE foldr1 #-}++-- | /O(n)/ Strict right monoidal fold+--+foldr' :: V.Unbox a => (a -> b -> b) -> b -> NonEmptyUVector a -> b+foldr' f b = V.foldr' f b. _neUvec+{-# INLINE foldr' #-}++-- | /O(n)/ Strict right semigroupal fold+--+foldr1' :: V.Unbox a => (a -> a -> a) -> NonEmptyUVector a -> a+foldr1' f = V.foldr1' f . _neUvec+{-# INLINE foldr1' #-}++-- | /O(n)/ Left monoidal fold with function applied to each element+-- and its index+--+ifoldl :: V.Unbox b => (a -> Int -> b -> a) -> a -> NonEmptyUVector b -> a+ifoldl f a = V.ifoldl f a . _neUvec+{-# INLINE ifoldl #-}++-- | /O(n)/ Strict left monoidal fold with function applied to each element+-- and its index+--+ifoldl' :: V.Unbox b => (a -> Int -> b -> a) -> a -> NonEmptyUVector b -> a+ifoldl' f a = V.ifoldl' f a . _neUvec+{-# INLINE ifoldl' #-}++-- | /O(n)/ Right monoidal fold with function applied to each element+-- and its index+--+ifoldr :: V.Unbox a => (Int -> a -> b -> b) -> b -> NonEmptyUVector a -> b+ifoldr f b = V.ifoldr f b . _neUvec+{-# INLINE ifoldr #-}++-- | /O(n)/ strict right monoidal fold with function applied to each element+-- and its index+--+ifoldr' :: V.Unbox a => (Int -> a -> b -> b) -> b -> NonEmptyUVector a -> b+ifoldr' f b = V.ifoldr' f b . _neUvec+{-# INLINE ifoldr' #-}++-- ---------------------------------------------------------------------- --+-- Specialised folds++-- | /O(n)/ Check if all elements satisfy the predicate.+--+all :: V.Unbox a => (a -> Bool) -> NonEmptyUVector a -> Bool+all f = V.all f . _neUvec+{-# INLINE all #-}++-- | /O(n)/ Check if any element satisfies the predicate.+--+any :: V.Unbox a => (a -> Bool) -> NonEmptyUVector a -> Bool+any f = V.any f . _neUvec+{-# INLINE any #-}++-- | /O(n)/ Check if all elements are @True@.+--+and :: NonEmptyUVector Bool -> Bool+and = V.and . _neUvec+{-# INLINE and #-}++-- | /O(n)/ Check if any element is @True@+--+or :: NonEmptyUVector Bool -> Bool+or = V.or . _neUvec+{-# INLINE or #-}++-- | /O(n)/ Compute the sum of the elements+--+sum :: (Num a, V.Unbox a) => NonEmptyUVector a -> a+sum = V.sum . _neUvec+{-# INLINE sum #-}++-- | /O(n)/ Compute the produce of the elements+--+product :: (Num a, V.Unbox a) => NonEmptyUVector a -> a+product = V.product . _neUvec+{-# INLINE product #-}++-- | /O(n)/ Yield the maximum element of the non-empty vector.+--+maximum :: (V.Unbox a, Ord a) => NonEmptyUVector a -> a+maximum = V.maximum . _neUvec+{-# INLINE maximum #-}++-- | /O(n)/ Yield the maximum element of a non-empty vector+-- according to the given comparison function.+--+maximumBy :: V.Unbox a => (a -> a -> Ordering) -> NonEmptyUVector a -> a+maximumBy f = V.maximumBy f . _neUvec+{-# INLINE maximumBy #-}++-- | /O(n)/ Yield the minimum element of the non-empty vector.+--+minimum :: (V.Unbox a, Ord a) => NonEmptyUVector a -> a+minimum = V.minimum . _neUvec+{-# INLINE minimum #-}++-- | /O(n)/ Yield the minimum element of the non-empty vector+-- according to the given comparison function.+--+minimumBy :: V.Unbox a => (a -> a -> Ordering) -> NonEmptyUVector a -> a+minimumBy f = V.minimumBy f . _neUvec+{-# INLINE minimumBy #-}++-- | /O(n)/ Yield the index of the minimum element of the+-- non-empty vector.+--+minIndex :: (V.Unbox a, Ord a) => NonEmptyUVector a -> Int+minIndex = V.minIndex . _neUvec+{-# INLINE minIndex #-}++-- | /O(n)/ Yield the index of the minimum element of the vector+-- according to the given comparison function.+--+minIndexBy :: V.Unbox a => (a -> a -> Ordering) -> NonEmptyUVector a -> Int+minIndexBy f = V.minIndexBy f . _neUvec+{-# INLINE minIndexBy #-}++-- | /O(n)/ Yield the index of the maximum element of the+-- non-empty vector.+--+maxIndex :: (V.Unbox a, Ord a) => NonEmptyUVector a -> Int+maxIndex = V.maxIndex . _neUvec+{-# INLINE maxIndex #-}++-- | /O(n)/ Yield the index of the maximum element of the vector+-- according to the given comparison function.+--+maxIndexBy :: V.Unbox a => (a -> a -> Ordering) -> NonEmptyUVector a -> Int+maxIndexBy f = V.maxIndexBy f . _neUvec+{-# INLINE maxIndexBy #-}++-- ---------------------------------------------------------------------- --+-- Monadic folds++-- | /O(n)/ Monadic fold+--+foldM :: (V.Unbox b, Monad m) => (a -> b -> m a) -> a -> NonEmptyUVector b -> m a+foldM f a = V.foldM f a . _neUvec+{-# INLINE foldM #-}++-- | /O(n)/ Monadic fold (action applied to each element and its index)+--+ifoldM :: (V.Unbox b, Monad m) => (a -> Int -> b -> m a) -> a -> NonEmptyUVector b -> m a+ifoldM f a = V.ifoldM f a . _neUvec+{-# INLINE ifoldM #-}++-- | /O(n)/ Strict monadic fold+--+foldM' :: (V.Unbox b, Monad m) => (a -> b -> m a) -> a -> NonEmptyUVector b -> m a+foldM' f a = V.foldM' f a . _neUvec+{-# INLINE foldM' #-}++-- | /O(n)/ Strict monadic fold (action applied to each element and its index)+--+ifoldM' :: (V.Unbox b, Monad m) => (a -> Int -> b -> m a) -> a -> NonEmptyUVector b -> m a+ifoldM' f a = V.ifoldM' f a . _neUvec+{-# INLINE ifoldM' #-}++-- | /O(n)/ Monadic semigroupal fold+--+fold1M :: (V.Unbox a, Monad m) => (a -> a -> m a) -> NonEmptyUVector a -> m a+fold1M f = V.fold1M f . _neUvec+{-# INLINE fold1M #-}++-- | /O(n)/ Strict monadic semigroupal fold+--+fold1M' :: (V.Unbox a, Monad m) => (a -> a -> m a) -> NonEmptyUVector a -> m a+fold1M' f = V.fold1M' f . _neUvec+{-# INLINE fold1M' #-}++-- | /O(n)/ Monadic fold that discards the result+--+foldM_ :: (V.Unbox b, Monad m) => (a -> b -> m a) -> a -> NonEmptyUVector b -> m ()+foldM_ f a = V.foldM_ f a . _neUvec+{-# INLINE foldM_ #-}++-- | /O(n)/ Monadic fold that discards the result (action applied to each+-- element and its index)+--+ifoldM_ :: (V.Unbox b, Monad m) => (a -> Int -> b -> m a) -> a -> NonEmptyUVector b -> m ()+ifoldM_ f a = V.ifoldM_ f a . _neUvec+{-# INLINE ifoldM_ #-}++-- | /O(n)/ Strict monadic fold that discards the result+--+foldM'_ :: (V.Unbox b, Monad m) => (a -> b -> m a) -> a -> NonEmptyUVector b -> m ()+foldM'_ f a = V.foldM'_ f a . _neUvec+{-# INLINE foldM'_ #-}++-- | /O(n)/ Strict monadic fold that discards the result (action applied to each+-- element and its index)+--+ifoldM'_ :: (V.Unbox b, Monad m) => (a -> Int -> b -> m a) -> a -> NonEmptyUVector b -> m ()+ifoldM'_ f a = V.ifoldM'_ f a . _neUvec+{-# INLINE ifoldM'_ #-}++-- | /O(n)/ Monadic semigroupal fold that discards the result+--+fold1M_ :: (V.Unbox a, Monad m) => (a -> a -> m a) -> NonEmptyUVector a -> m ()+fold1M_ f = V.fold1M_ f . _neUvec+{-# INLINE fold1M_ #-}++-- | /O(n)/ Strict monadic semigroupal fold that discards the result+--+fold1M'_ :: (V.Unbox a, Monad m) => (a -> a -> m a) -> NonEmptyUVector a -> m ()+fold1M'_ f = V.fold1M'_ f . _neUvec+{-# INLINE fold1M'_ #-}++-- ---------------------------------------------------------------------- --+-- Prefix sums (scans)++-- | /O(n)/ Prescan+--+prescanl :: (V.Unbox a, V.Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a+prescanl f a = NonEmptyUVector . V.prescanl f a . _neUvec+{-# INLINE prescanl #-}++-- | /O(n)/ Prescan with strict accumulator+--+prescanl' :: (V.Unbox a, V.Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a+prescanl' f a = NonEmptyUVector . V.prescanl' f a . _neUvec+{-# INLINE prescanl' #-}++-- | /O(n)/ Scan+--+postscanl :: (V.Unbox a, V.Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a+postscanl f a = NonEmptyUVector . V.postscanl f a . _neUvec+{-# INLINE postscanl #-}++-- | /O(n)/ Scan with a strict accumulator+--+postscanl' :: (V.Unbox a, V.Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a+postscanl' f a = NonEmptyUVector . V.postscanl' f a . _neUvec+{-# INLINE postscanl' #-}++-- | /O(n)/ Haskell-style scan+--+scanl :: (V.Unbox a, V.Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a+scanl f a = NonEmptyUVector . V.scanl f a . _neUvec+{-# INLINE scanl #-}++-- | /O(n)/ Haskell-style scan with strict accumulator+--+scanl' :: (V.Unbox a, V.Unbox b) => (a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a+scanl' f a = NonEmptyUVector . V.scanl' f a . _neUvec+{-# INLINE scanl' #-}++-- | /O(n)/ Semigroupal left scan+--+scanl1 :: V.Unbox a => (a -> a -> a) -> NonEmptyUVector a -> NonEmptyUVector a+scanl1 f = NonEmptyUVector . V.scanl1 f . _neUvec+{-# INLINE scanl1 #-}++-- | /O(n)/ Strict semigroupal scan+--+scanl1' :: V.Unbox a => (a -> a -> a) -> NonEmptyUVector a -> NonEmptyUVector a+scanl1' f = NonEmptyUVector . V.scanl1' f . _neUvec+{-# INLINE scanl1' #-}++-- | /O(n)/ Scan over a vector with its index+--+iscanl :: (V.Unbox a, V.Unbox b) => (Int -> a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a+iscanl f a = NonEmptyUVector . V.iscanl f a . _neUvec+{-# INLINE iscanl #-}++-- | /O(n)/ Scan over a vector with its index with strict accumulator+--+iscanl' :: (V.Unbox a, V.Unbox b) => (Int -> a -> b -> a) -> a -> NonEmptyUVector b -> NonEmptyUVector a+iscanl' f a = NonEmptyUVector . V.iscanl' f a . _neUvec+{-# INLINE iscanl' #-}++-- | /O(n)/ Right-to-left prescan+--+prescanr :: (V.Unbox a, V.Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b+prescanr f b = NonEmptyUVector . V.prescanr f b . _neUvec+{-# INLINE prescanr #-}++-- | /O(n)/ Right-to-left prescan with strict accumulator+--+prescanr' :: (V.Unbox a, V.Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b+prescanr' f b = NonEmptyUVector . V.prescanr' f b . _neUvec+{-# INLINE prescanr' #-}++-- | /O(n)/ Right-to-left scan+--+postscanr :: (V.Unbox a, V.Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b+postscanr f b = NonEmptyUVector . V.postscanr f b . _neUvec+{-# INLINE postscanr #-}++-- | /O(n)/ Right-to-left scan with strict accumulator+--+postscanr' :: (V.Unbox a, V.Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b+postscanr' f b = NonEmptyUVector . V.postscanr' f b . _neUvec+{-# INLINE postscanr' #-}++-- | /O(n)/ Right-to-left Haskell-style scan+--+scanr :: (V.Unbox a, V.Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b+scanr f b = NonEmptyUVector . V.scanr f b . _neUvec+{-# INLINE scanr #-}++-- | /O(n)/ Right-to-left Haskell-style scan with strict accumulator+--+scanr' :: (V.Unbox a, V.Unbox b) => (a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b+scanr' f b = NonEmptyUVector . V.scanr' f b . _neUvec+{-# INLINE scanr' #-}++-- | /O(n)/ Right-to-left Haskell-style semigroupal scan+--+scanr1 :: V.Unbox a => (a -> a -> a) -> NonEmptyUVector a -> NonEmptyUVector a+scanr1 f = NonEmptyUVector . V.scanr1 f . _neUvec+{-# INLINE scanr1 #-}++-- | /O(n)/ Right-to-left Haskell-style semigroupal scan with strict accumulator+--+scanr1' :: V.Unbox a => (a -> a -> a) -> NonEmptyUVector a -> NonEmptyUVector a+scanr1' f = NonEmptyUVector . V.scanr1' f . _neUvec+{-# INLINE scanr1' #-}++-- | /O(n)/ Right-to-left scan over a vector with its index+--+iscanr :: (V.Unbox a, V.Unbox b) => (Int -> a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b+iscanr f b = NonEmptyUVector . V.iscanr f b . _neUvec+{-# INLINE iscanr #-}++-- | /O(n)/ Right-to-left scan over a vector with its index and a strict+-- accumulator+--+iscanr' :: (V.Unbox a, V.Unbox b) => (Int -> a -> b -> b) -> b -> NonEmptyUVector a -> NonEmptyUVector b+iscanr' f b = NonEmptyUVector . V.iscanr' f b . _neUvec+{-# INLINE iscanr' #-}++-- | /O(n)/ The 'intersperse' function takes an element and a 'NonEmptyUVector'+-- and "intersperses" that element between the elements of the 'NonEmptyUVector'.+--+-- >>> intersperse 0 (unsafeFromList [1,2,3])+-- [1,0,2,0,3]+--+-- >>> intersperse 0 (singleton 1)+-- [1]+--+intersperse :: forall (a :: Type) . V.Unbox a => a -> NonEmptyUVector a -> NonEmptyUVector a+intersperse sep nev@(NonEmptyUVector v)+ | V.length v <= 1 = nev+ | otherwise = unsafeCreate $ do+ let n = V.length v+ let newLen = 2*n - 1+ mv <- V.unsafeThaw $ V.replicate newLen (V.unsafeHead v) -- Create mutable vector++ -- Fill the first element+ unsafeWrite mv 0 (V.unsafeIndex v 0)++ -- Fill remaining elements with separators+ let go i j+ | j >= n = pure ()+ | otherwise = do+ unsafeWrite mv i sep+ unsafeWrite mv (i+1) (V.unsafeIndex v j)+ go (i+2) (j+1)++ go 1 1+ pure mv+{-# INLINE intersperse #-}++-- | /O(n)/ Split a vector into a list of slices of the input vector.+--+-- The concatenation of this list of slices is equal to the argument vector,+-- and each slice contains only equal elements. Returns nothing if no equal+-- elements are found.+--+-- This is the equivalent of 'groupBy (==)'.+--+-- >>> import qualified Data.NonEmptyUVector as NEV+-- >>> NEV.group (NEV.unsafeFromList "Mississippi")+-- "M" :| ["i","ss","i","ss","i","pp","i"]+--+-- See also 'Data.Vector.group'.+--+-- @since 1.0+--+group :: (V.Unbox a, Eq a) => NonEmptyUVector a -> NonEmpty (NonEmptyUVector a)+group = groupBy (==)++-- | /O(n)/ Split a vector into a list of slices.+--+--+-- The concatenation of this list of slices is equal to the argument vector,+-- and each slice contains only equal elements, as determined by the equality+-- predicate function.+--++-- >>> import qualified Data.NonEmptyUVector as NEV+-- >>> import Data.Char (isUpper)+-- >>> NEV.groupBy (\a b -> isUpper a == isUpper b) (NEV.unsafeFromList "Mississippi River")+-- "M" :| ["ississippi ","R","iver"]+--+-- See also 'Data.Vector.groupBy'.+--+-- @since 1.0+--+groupBy+ :: (Eq a, V.Unbox a)+ => (a -> a -> Bool)+ -> NonEmptyUVector a+ -> NonEmpty (NonEmptyUVector a)+groupBy f = go+ where+ go v =+ let+ h = head v+ t = NonEmptyUVector $ tail v+ in case findIndex (not . f h) t of+ Nothing -> v :| []+ Just n ->+ let+ z = NonEmptyUVector $ unsafeTake (n+1) v+ x = NonEmptyUVector $ unsafeDrop (n+1) v+ in z <| go x
+ src/Data/Vector/NonEmpty/Unboxed/Internal.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE StandaloneDeriving #-}+-- |+-- Module : Data.Vector.NonEmpty.Unboxed.Internal+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Internal module exposing the constructors for+-- t'NonEmptyUVector' and t'NonEmptyMUVector'.+--+-- /Warning/: Since the constructors are exposed here, by using this+-- module, you take on the risks that you break the non-emptiness+-- invariants of the main modules. Use at your own risk.+--+-- @since 1.0+--+module Data.Vector.NonEmpty.Unboxed.Internal+( -- * Immutable unboxed vectors+ NonEmptyUVector(..)+ -- * Mutable unboxed vectors+, NonEmptyMUVector(..)+ -- ** Mutable unboxed vector aliases+, NonEmptyIOUVector+, NonEmptySTUVector+) where+++import Control.DeepSeq (NFData)+import Control.Monad.ST++import Data.Data (Data)+import qualified Data.Vector.Unboxed as V+#if __GLASGOW_HASKELL__ < 912+import Data.Typeable (Typeable)+#endif+import Data.Vector.Unboxed.Mutable (MVector)++import qualified Text.Read as Read+++-- ---------------------------------------------------------------------- --+-- Non-empty immutable unboxed vectors++-- | t'NonEmptyUVector' is a thin wrapper around 'Data.Vector.Unboxed.Vector' that+-- witnesses an API requiring non-empty construction,+-- initialization, and generation of non-empty vectors by design.+--+-- A newtype wrapper was chosen so that no new pointer indirection+-- is introduced when working with 'Data.Vector.Unboxed.Vector's, and all performance+-- characteristics inherited from the "Data.Unboxed.Vector" API still apply.+--+-- @since 1.0+--+newtype NonEmptyUVector a = NonEmptyUVector+ { _neUvec :: V.Vector a+ } deriving+ ( Eq, Ord+ , Data, NFData+ , Semigroup+#if __GLASGOW_HASKELL__ < 912+ , Typeable+#endif+ ) ++deriving via (V.Vector a) instance (Show a, V.Unbox a) => + Show (NonEmptyUVector a)++instance (V.Unbox a, Read a) => Read (NonEmptyUVector a) where+ readPrec = Read.readPrec >>= \case+ [] -> Read.pfail+ as -> return (NonEmptyUVector $ V.fromList as)++-- ---------------------------------------------------------------------- --+-- Non-empty unboxed mutable vectors++-- | t'NonEmptyMUVector' is a thin wrapper around 'MVector' that+-- witnesses an API requiring non-empty construction,+-- initialization, and generation of non-empty vectors by design.+--+-- A newtype wrapper was chosen so that no new pointer indirection+-- is introduced when working with 'MVector's, and all performance+-- characteristics inherited from the 'MVector' API still apply.+--+-- @since 1.0+--+newtype NonEmptyMUVector s a = NonEmptyMUVector+ { _nemUvec :: MVector s a }+#if __GLASGOW_HASKELL__ < 912+ deriving (Typeable)+#endif++-- | t'NonEmptyMUVector' parametrized by 'Control.Monad.Primitive.PrimState' 'IO'.+--+-- @since 1.0+--+type NonEmptyIOUVector = NonEmptyMUVector RealWorld++-- | t'NonEmptyMUVector' parametrized by @t'Control.Monad.Primitive.PrimState' ('ST' s)@.+--+-- @since 1.0+--+type NonEmptySTUVector s = NonEmptyMUVector s
+ src/Data/Vector/NonEmpty/Unboxed/Mutable.hs view
@@ -0,0 +1,452 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module : Data.Vector.NonEmpty.Unboxed.Mutable+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Non-empty mutable unboxed vectors.+--+module Data.Vector.NonEmpty.Unboxed.Mutable+( -- * Mutable boxed vectors+ NonEmptyMUVector+, NonEmptyIOUVector+, NonEmptySTUVector++ -- * Accessors+ -- ** Length information+, length++ -- ** Extracting subvectors+, slice, init, tail, take, drop, splitAt+, unsafeSlice, unsafeTake, unsafeDrop++ -- ** Overlapping+, overlaps++ -- ** Conversions+, fromMVector, toMVector, unsafeFromMVector++ -- ** Initialisation+, new, new1, unsafeNew+, replicate, replicate1+, replicateM, replicate1M+, clone++ -- ** Growing+, grow, unsafeGrow++ -- ** Restricting memory usage+, clear++ -- * Accessing individual elements+, read, write, modify, swap+, unsafeRead, unsafeWrite, unsafeModify, unsafeSwap++ -- * Modifying vectors+, nextPermutation++ -- ** Filling and copying+, set, copy, move, unsafeCopy, unsafeMove+) where+++import Prelude (Bool, Int, Ord, (.), max)++import Control.Monad.Primitive++import Data.Functor+import Data.Maybe (Maybe(..))+import Data.Vector.Unboxed.Mutable (MVector)+import qualified Data.Vector.Unboxed.Mutable as M+import Data.Vector.NonEmpty.Unboxed.Internal+++-- ---------------------------------------------------------------------- --+-- Length information++-- | Length of the mutable vector.+length :: M.Unbox a => NonEmptyMUVector s a -> Int+length = M.length . _nemUvec+{-# INLINE length #-}++-- ---------------------------------------------------------------------- --+-- Extracting subvectors++-- | Yield a part of the mutable vector without copying.+--+slice :: M.Unbox a => Int -> Int -> NonEmptyMUVector s a -> MVector s a+slice n m = M.slice n m . _nemUvec+{-# INLINE slice #-}++-- | Yield at the first n elements without copying.+--+take :: M.Unbox a => Int -> NonEmptyMUVector s a -> MVector s a+take n = M.take n . _nemUvec+{-# INLINE take #-}++-- | Yield all but the first n elements without copying.+--+drop :: M.Unbox a => Int -> NonEmptyMUVector s a -> MVector s a+drop n = M.drop n . _nemUvec+{-# INLINE drop #-}++-- | Yield the first n elements paired with the remainder without copying.+--+splitAt :: M.Unbox a => Int -> NonEmptyMUVector s a -> (MVector s a, MVector s a)+splitAt n = M.splitAt n . _nemUvec+{-# INLINE splitAt #-}++-- | Yield all but the last element without copying.+--+init :: M.Unbox a => NonEmptyMUVector s a -> MVector s a+init = M.unsafeInit . _nemUvec+{-# INLINE init #-}++-- | Yield all but the first element without copying.+--+tail :: M.Unbox a => NonEmptyMUVector s a -> MVector s a+tail = M.unsafeTail . _nemUvec+{-# INLINE tail #-}++-- | Yield a part of the mutable vector without copying it. No bounds checks+-- are performed.+--+unsafeSlice+ :: M.Unbox a+ => Int+ -- ^ starting index+ -> Int+ -- ^ length of the slice+ -> NonEmptyMUVector s a+ -> MVector s a+unsafeSlice n m = M.unsafeSlice n m . _nemUvec+{-# INLINE unsafeSlice #-}++-- | Yield the first n elements without copying. The vector must contain at+-- least n elements but this is not checked.+--+unsafeTake :: M.Unbox a => Int -> NonEmptyMUVector s a -> MVector s a+unsafeTake n = M.unsafeTake n . _nemUvec+{-# INLINE unsafeTake #-}++-- | Yield all but the first n elements without copying. The vector must+-- contain at least n elements but this is not checked.+--+unsafeDrop :: M.Unbox a => Int -> NonEmptyMUVector s a -> MVector s a+unsafeDrop n = M.unsafeDrop n . _nemUvec+{-# INLINE unsafeDrop #-}++-- ---------------------------------------------------------------------- --+-- Overlapping++-- | Check whether two vectors overlap.+--+overlaps :: M.Unbox a => NonEmptyMUVector s a -> NonEmptyMUVector s a -> Bool+overlaps (NonEmptyMUVector v) (NonEmptyMUVector u) = M.overlaps v u+{-# INLINE overlaps #-}++-- ---------------------------------------------------------------------- --+-- Conversion++-- | Convert a mutable vector to a non-empty mutable vector+--+fromMVector :: M.Unbox a => MVector s a -> Maybe (NonEmptyMUVector s a)+fromMVector v = if M.null v then Nothing else Just (NonEmptyMUVector v)++-- | Convert a non-empty mutable vector to a mutable vector+--+toMVector :: M.Unbox a => NonEmptyMUVector s a -> MVector s a+toMVector = _nemUvec++-- | Convert a mutable vector to a non-empty mutable vector+--+-- /Warning:/ this function is unsafe and can result in empty non-empty+-- mutable vectors. If you call this function, the onus is on you to+-- make sure the mutable vector being converted is not empty.+--+unsafeFromMVector :: M.Unbox a => MVector s a -> NonEmptyMUVector s a+unsafeFromMVector = NonEmptyMUVector+{-# INLINE unsafeFromMVector #-}++-- ---------------------------------------------------------------------- --+-- Initialisation++-- | Create a mutable vector of the given length.+--+new+ :: (PrimMonad m, M.Unbox a)+ => Int+ -> m (Maybe (NonEmptyMUVector (PrimState m) a))+new = fmap fromMVector . M.new+{-# INLINE new #-}++-- | Create a mutable vector of the given length which is+-- @max n 1@.+--+new1+ :: (PrimMonad m, M.Unbox a)+ => Int+ -> m (NonEmptyMUVector (PrimState m) a)+new1 n = fmap unsafeFromMVector (M.new (max n 1))+{-# INLINE new1 #-}++-- | Create a mutable vector of the given length. The memory is not initialized.+--+unsafeNew+ :: (PrimMonad m, M.Unbox a)+ => Int+ -> m (Maybe (NonEmptyMUVector (PrimState m) a))+unsafeNew = fmap fromMVector . M.unsafeNew+{-# INLINE unsafeNew #-}++-- | Create a mutable vector of the given length (0 if the length is negative)+-- and fill it with an initial value.+--+replicate+ :: (PrimMonad m, M.Unbox a)+ => Int+ -> a+ -> m (Maybe (NonEmptyMUVector (PrimState m) a))+replicate n a = fmap fromMVector (M.replicate n a)+{-# INLINE replicate #-}++-- | Create a mutable vector of the length @max n 1@ for a given length,+-- and fill it with an initial value.+--+replicate1+ :: (PrimMonad m, M.Unbox a)+ => Int+ -> a+ -> m (NonEmptyMUVector (PrimState m) a)+replicate1 n a = fmap unsafeFromMVector (M.replicate (max n 1) a)+{-# INLINE replicate1 #-}++-- | Create a mutable vector of the given length (0 if the length is negative)+-- and fill it with values produced by repeatedly executing the monadic action.+--+replicateM+ :: (PrimMonad m, M.Unbox a)+ => Int+ -> m a+ -> m (Maybe (NonEmptyMUVector (PrimState m) a))+replicateM n a = fmap fromMVector (M.replicateM n a)+{-# INLINE replicateM #-}++-- | Create a mutable vector of the length @max n 1@ for a given length,+-- and fill it with values produced by repeatedly executing the monadic action.+--+replicate1M+ :: (PrimMonad m, M.Unbox a)+ => Int+ -> m a+ -> m (Maybe (NonEmptyMUVector (PrimState m) a))+replicate1M n a = fmap fromMVector (M.replicateM (max n 1) a)+{-# INLINE replicate1M #-}++-- | Create a copy of a mutable vector.+--+clone+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> m (NonEmptyMUVector (PrimState m) a)+clone (NonEmptyMUVector v) = fmap NonEmptyMUVector (M.clone v)+{-# INLINE clone #-}++-- ---------------------------------------------------------------------- --+-- Growing++-- | Grow a vector by the given number of elements. The number must be+-- positive.+--+grow+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> Int+ -> m (NonEmptyMUVector (PrimState m) a)+grow (NonEmptyMUVector v) n = fmap NonEmptyMUVector (M.grow v n)+{-# INLINE grow #-}++-- | Grow a vector by the given number of elements. The number must be+-- positive but this is not checked.+unsafeGrow+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> Int+ -> m (NonEmptyMUVector (PrimState m) a)+unsafeGrow (NonEmptyMUVector v) n = fmap NonEmptyMUVector (M.unsafeGrow v n)+{-# INLINE unsafeGrow #-}++-- ---------------------------------------------------------------------- --+-- Restricting memory usage++-- | Reset all elements of the vector to some undefined value, clearing all+-- references to external objects. This is usually a noop for unboxed vectors.+clear :: (PrimMonad m, M.Unbox a) => NonEmptyMUVector (PrimState m) a -> m ()+clear = M.clear . _nemUvec+{-# INLINE clear #-}++-- ---------------------------------------------------------------------- --+-- Accessing individual elements++-- | Yield the element at the given position.+--+read+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> Int+ -> m a+read (NonEmptyMUVector v) n = M.read v n+{-# INLINE read #-}++-- | Replace the element at the given position.+--+write+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> Int+ -> a+ -> m ()+write (NonEmptyMUVector v) n a = M.write v n a+{-# INLINE write #-}++-- | Modify the element at the given position.+--+modify+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> (a -> a)+ -> Int+ -> m ()+modify (NonEmptyMUVector v) f n = M.modify v f n+{-# INLINE modify #-}++-- | Swap the elements at the given positions.+--+swap+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> Int+ -> Int+ -> m ()+swap (NonEmptyMUVector v) n m = M.swap v n m+{-# INLINE swap #-}++-- | Yield the element at the given position. No bounds checks are performed.+--+unsafeRead+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> Int+ -> m a+unsafeRead (NonEmptyMUVector v) n = M.unsafeRead v n+{-# INLINE unsafeRead #-}++-- | Replace the element at the given position. No bounds checks are performed.+--+unsafeWrite+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> Int+ -> a+ -> m ()+unsafeWrite (NonEmptyMUVector v) n a = M.unsafeWrite v n a+{-# INLINE unsafeWrite #-}++-- | Modify the element at the given position. No bounds checks are performed.+--+unsafeModify+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> (a -> a)+ -> Int+ -> m ()+unsafeModify (NonEmptyMUVector v) f n = M.unsafeModify v f n+{-# INLINE unsafeModify #-}++-- | Swap the elements at the given positions. No bounds checks are performed.+--+unsafeSwap :: (PrimMonad m, M.Unbox a) => NonEmptyMUVector (PrimState m) a -> Int -> Int -> m ()+unsafeSwap (NonEmptyMUVector v) n m = M.unsafeSwap v n m+{-# INLINE unsafeSwap #-}++-- ---------------------------------------------------------------------- --+-- Filling and copying++-- | Set all elements of the vector to the given value.+--+set :: (PrimMonad m, M.Unbox a) => NonEmptyMUVector (PrimState m) a -> a -> m ()+set (NonEmptyMUVector v) a = M.set v a+{-# INLINE set #-}++-- | Copy a vector. The two vectors must have the same length and may not+-- overlap.+--+copy+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> NonEmptyMUVector (PrimState m) a+ -> m ()+copy (NonEmptyMUVector v) (NonEmptyMUVector v') = M.copy v v'+{-# INLINE copy #-}++-- | Copy a vector. The two vectors must have the same length and may not+-- overlap. This is not checked.+--+unsafeCopy+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -- ^ target+ -> NonEmptyMUVector (PrimState m) a+ -- ^ source+ -> m ()+unsafeCopy (NonEmptyMUVector v) (NonEmptyMUVector v') = M.unsafeCopy v v'+{-# INLINE unsafeCopy #-}++-- | Move the contents of a vector. The two vectors must have the same+-- length.+--+-- If the vectors do not overlap, then this is equivalent to 'copy'.+-- Otherwise, the copying is performed as if the source vector were+-- copied to a temporary vector and then the temporary vector was copied+-- to the target vector.+--+move+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -> NonEmptyMUVector (PrimState m) a -> m ()+move (NonEmptyMUVector v) (NonEmptyMUVector v') = M.move v v'+{-# INLINE move #-}++-- | Move the contents of a vector. The two vectors must have the same+-- length, but this is not checked.+--+-- If the vectors do not overlap, then this is equivalent to 'unsafeCopy'.+-- Otherwise, the copying is performed as if the source vector were+-- copied to a temporary vector and then the temporary vector was copied+-- to the target vector.+--+unsafeMove+ :: (PrimMonad m, M.Unbox a)+ => NonEmptyMUVector (PrimState m) a+ -- ^ target+ -> NonEmptyMUVector (PrimState m) a+ -- ^ source+ -> m ()+unsafeMove (NonEmptyMUVector v) (NonEmptyMUVector v') = M.unsafeMove v v'+{-# INLINE unsafeMove #-}++-- | Compute the next (lexicographically) permutation of given vector in-place.+-- Returns False when input is the last permtuation+--+nextPermutation+ :: (PrimMonad m,Ord e, M.Unbox e)+ => NonEmptyMUVector (PrimState m) e+ -> m Bool+nextPermutation = M.nextPermutation . _nemUvec+{-# INLINE nextPermutation #-}
test/Main.hs view
@@ -1,6 +1,6 @@ -- | -- Module : Main (tests)--- Copyright : (c) 2019-2026 Emily Pillmore+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross -- License : BSD -- Maintainer : Emily Pillmore <emilypi@cohomolo.gy> -- Stability : Experimental@@ -12,16 +12,27 @@ import qualified Test.Data.Vector.NonEmpty.Accessors as Accessors+import qualified Test.Data.Vector.NonEmpty.AccessorsU as AccessorsU import qualified Test.Data.Vector.NonEmpty.Construction as Construction+import qualified Test.Data.Vector.NonEmpty.ConstructionU as ConstructionU import qualified Test.Data.Vector.NonEmpty.Conversion as Conversion+import qualified Test.Data.Vector.NonEmpty.ConversionU as ConversionU import qualified Test.Data.Vector.NonEmpty.Elementwise as Elementwise+import qualified Test.Data.Vector.NonEmpty.ElementwiseU as ElementwiseU import qualified Test.Data.Vector.NonEmpty.Folds as Folds+import qualified Test.Data.Vector.NonEmpty.FoldsU as FoldsU import qualified Test.Data.Vector.NonEmpty.Grouping as Grouping+import qualified Test.Data.Vector.NonEmpty.GroupingU as GroupingU import qualified Test.Data.Vector.NonEmpty.Instances as Instances+import qualified Test.Data.Vector.NonEmpty.InstancesU as InstancesU import qualified Test.Data.Vector.NonEmpty.Modification as Modification+import qualified Test.Data.Vector.NonEmpty.ModificationU as ModificationU import qualified Test.Data.Vector.NonEmpty.Mutable as Mutable+import qualified Test.Data.Vector.NonEmpty.MutableU as MutableU import qualified Test.Data.Vector.NonEmpty.Predicates as Predicates+import qualified Test.Data.Vector.NonEmpty.PredicatesU as PredicatesU import qualified Test.Data.Vector.NonEmpty.Scans as Scans+import qualified Test.Data.Vector.NonEmpty.ScansU as ScansU import Test.Tasty @@ -29,14 +40,25 @@ main :: IO () main = defaultMain $ testGroup "NonEmptyVector tests" [ Accessors.tests+ , AccessorsU.tests , Construction.tests+ , ConstructionU.tests , Conversion.tests+ , ConversionU.tests , Modification.tests+ , ModificationU.tests , Elementwise.tests+ , ElementwiseU.tests , Predicates.tests+ , PredicatesU.tests , Grouping.tests+ , GroupingU.tests , Folds.tests+ , FoldsU.tests , Scans.tests+ , ScansU.tests , Instances.tests+ , InstancesU.tests , Mutable.tests+ , MutableU.tests ]
+ test/Test/Data/Vector/NonEmpty/AccessorsU.hs view
@@ -0,0 +1,181 @@+-- |+-- Module : Test.Data.Vector.NonEmpty.AccessorsU+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Properties for length information, indexing, and slicing.+--+module Test.Data.Vector.NonEmpty.AccessorsU+( tests+) where+++import Data.Functor.Identity (Identity(..))+import qualified Data.List as List+import qualified Data.Vector.Unboxed as V+import Data.Vector.NonEmpty.Unboxed (NonEmptyUVector)+import qualified Data.Vector.NonEmpty.Unboxed as NEV++import Test.Data.Vector.NonEmpty.Util+import Test.QuickCheck+import Test.Tasty+import Test.Tasty.QuickCheck+++tests :: TestTree+tests = testGroup "Accessors (unboxed)"+ [ testGroup "Length information"+ [ testProperty "prop_length" prop_length+ ]+ , testGroup "Indexing"+ [ testProperty "prop_head" prop_head+ , testProperty "prop_last" prop_last+ , testProperty "prop_index" prop_index+ , testProperty "prop_index_out_of_bounds" prop_index_out_of_bounds+ , testProperty "prop_index_maybe" prop_index_maybe+ , testProperty "prop_unsafeIndex" prop_unsafeIndex+ ]+ , testGroup "Monadic indexing"+ [ testProperty "prop_headM" prop_headM+ , testProperty "prop_lastM" prop_lastM+ , testProperty "prop_indexM" prop_indexM+ , testProperty "prop_indexM_out_of_bounds" prop_indexM_out_of_bounds+ , testProperty "prop_unsafeIndexM" prop_unsafeIndexM+ ]+ , testGroup "Slicing"+ [ testProperty "prop_tail" prop_tail+ , testProperty "prop_init" prop_init+ , testProperty "prop_uncons" prop_uncons+ , testProperty "prop_unsnoc" prop_unsnoc+ , testProperty "prop_slice" prop_slice+ , testProperty "prop_slice_out_of_bounds" prop_slice_out_of_bounds+ , testProperty "prop_take" prop_take+ , testProperty "prop_drop" prop_drop+ , testProperty "prop_splitAt" prop_splitAt+ , testProperty "prop_unsafeSlice" prop_unsafeSlice+ , testProperty "prop_unsafeTake" prop_unsafeTake+ , testProperty "prop_unsafeDrop" prop_unsafeDrop+ ]+ ]++-- ---------------------------------------------------------------------- --+-- Length information++prop_length :: NonEmptyUVector Int -> Property+prop_length v = NEV.length v === List.length (elemsU v)++-- ---------------------------------------------------------------------- --+-- Indexing++prop_head :: NonEmptyUVector Int -> Property+prop_head v = [NEV.head v] === List.take 1 (elemsU v)++prop_last :: NonEmptyUVector Int -> Property+prop_last v = [NEV.last v] === List.take 1 (List.reverse (elemsU v))++prop_index :: NonEmptyUVector Int -> Property+prop_index v = forAll (genIndexU v) $ \i ->+ Just (v NEV.! i) === lookupList i (elemsU v)++prop_index_out_of_bounds :: NonEmptyUVector Int -> Property+prop_index_out_of_bounds v = forAll (genOutOfBoundsU v) $ \i ->+ throws (v NEV.! i)++prop_index_maybe :: NonEmptyUVector Int -> Int -> Property+prop_index_maybe v i = v NEV.!? i === lookupList i (elemsU v)++prop_unsafeIndex :: NonEmptyUVector Int -> Property+prop_unsafeIndex v = forAll (genIndexU v) $ \i ->+ Just (NEV.unsafeIndex v i) === lookupList i (elemsU v)++-- ---------------------------------------------------------------------- --+-- Monadic indexing++prop_headM :: NonEmptyUVector Int -> Property+prop_headM v = [runIdentity (NEV.headM v)] === List.take 1 (elemsU v)++prop_lastM :: NonEmptyUVector Int -> Property+prop_lastM v =+ [runIdentity (NEV.lastM v)] === List.take 1 (List.reverse (elemsU v))++prop_indexM :: NonEmptyUVector Int -> Property+prop_indexM v = forAll (genIndexU v) $ \i ->+ Just (runIdentity (NEV.indexM v i)) === lookupList i (elemsU v)++prop_indexM_out_of_bounds :: NonEmptyUVector Int -> Property+prop_indexM_out_of_bounds v = forAll (genOutOfBoundsU v) $ \i ->+ throws (runIdentity (NEV.indexM v i))++prop_unsafeIndexM :: NonEmptyUVector Int -> Property+prop_unsafeIndexM v = forAll (genIndexU v) $ \i ->+ Just (runIdentity (NEV.unsafeIndexM v i)) === lookupList i (elemsU v)++-- ---------------------------------------------------------------------- --+-- Slicing++prop_tail :: NonEmptyUVector Int -> Property+prop_tail v = V.toList (NEV.tail v) === List.drop 1 (elemsU v)++prop_init :: NonEmptyUVector Int -> Property+prop_init v =+ V.toList (NEV.init v) === List.take (List.length as - 1) as+ where+ as = elemsU v++prop_uncons :: NonEmptyUVector Int -> Property+prop_uncons v = ([a], V.toList as) === List.splitAt 1 (elemsU v)+ where+ (a, as) = NEV.uncons v++prop_unsnoc :: NonEmptyUVector Int -> Property+prop_unsnoc v =+ (V.toList as, [a]) === List.splitAt (List.length (elemsU v) - 1) (elemsU v)+ where+ (as, a) = NEV.unsnoc v++prop_slice :: NonEmptyUVector Int -> Property+prop_slice v = forAll (genSliceU v) $ \(i, m) ->+ V.toList (NEV.slice i m v) === List.take m (List.drop i (elemsU v))++prop_slice_out_of_bounds :: NonEmptyUVector Int -> Property+prop_slice_out_of_bounds v = forAll genBadSlice $ \(i, m) ->+ throws (V.toList (NEV.slice i m v))+ where+ n = NEV.length v++ genBadSlice = oneof+ [ (,) <$> choose (-10, -1) <*> choose (0, n)+ , (,) <$> choose (0, n) <*> choose (-10, -1)+ , do+ i <- choose (0, n)+ m <- choose (n - i + 1, n - i + 10)+ pure (i, m)+ ]++prop_take :: Int -> NonEmptyUVector Int -> Property+prop_take n v = V.toList (NEV.take n v) === List.take n (elemsU v)++prop_drop :: Int -> NonEmptyUVector Int -> Property+prop_drop n v = V.toList (NEV.drop n v) === List.drop n (elemsU v)++prop_splitAt :: Int -> NonEmptyUVector Int -> Property+prop_splitAt n v =+ (V.toList as, V.toList bs) === List.splitAt n (elemsU v)+ where+ (as, bs) = NEV.splitAt n v++prop_unsafeSlice :: NonEmptyUVector Int -> Property+prop_unsafeSlice v = forAll (genSliceU v) $ \(i, m) ->+ V.toList (NEV.unsafeSlice i m v) === List.take m (List.drop i (elemsU v))++prop_unsafeTake :: NonEmptyUVector Int -> Property+prop_unsafeTake v = forAll (choose (0, NEV.length v)) $ \n ->+ V.toList (NEV.unsafeTake n v) === List.take n (elemsU v)++prop_unsafeDrop :: NonEmptyUVector Int -> Property+prop_unsafeDrop v = forAll (choose (0, NEV.length v)) $ \n ->+ V.toList (NEV.unsafeDrop n v) === List.drop n (elemsU v)
+ test/Test/Data/Vector/NonEmpty/ConstructionU.hs view
@@ -0,0 +1,316 @@+-- |+-- Module : Test.Data.Vector.NonEmpty.Construction+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Properties for initialization, unfolding, enumeration, and+-- concatenation.+--+-- The 'Maybe'-valued constructors must yield 'Nothing' exactly when the+-- result would be empty, and the @*1@ variants must clamp their size to at+-- least one.+--+module Test.Data.Vector.NonEmpty.ConstructionU+( tests+) where+++import qualified Data.List as List+import Data.List.NonEmpty (NonEmpty(..))+import qualified Data.Vector.Unboxed as V+import qualified Data.Vector.NonEmpty.Unboxed as NEV+import Data.Vector.NonEmpty.Unboxed.Internal (NonEmptyUVector(..))++import Test.Data.Vector.NonEmpty.Util+import Test.QuickCheck+import Test.Tasty+import Test.Tasty.QuickCheck+++tests :: TestTree+tests = testGroup "Construction (unboxed)"+ [ testGroup "Initialization"+ [ testProperty "prop_singleton" prop_singleton+ , testProperty "prop_replicate" prop_replicate+ , testProperty "prop_replicate1" prop_replicate1+ , testProperty "prop_generate" prop_generate+ , testProperty "prop_generate1" prop_generate1+ , testProperty "prop_iterateN" prop_iterateN+ , testProperty "prop_iterateN1" prop_iterateN1+ ]+ , testGroup "Monadic initialization"+ [ testProperty "prop_replicateM" prop_replicateM+ , testProperty "prop_replicate1M" prop_replicate1M+ , testProperty "prop_generateM" prop_generateM+ , testProperty "prop_generate1M" prop_generate1M+ , testProperty "prop_iterateNM" prop_iterateNM+ , testProperty "prop_iterateN1M" prop_iterateN1M+ , testProperty "prop_create" prop_create+ , testProperty "prop_unsafeCreate" prop_unsafeCreate+ , testProperty "prop_createT" prop_createT+ , testProperty "prop_unsafeCreateT" prop_unsafeCreateT+ ]+ , testGroup "Unfolding"+ [ testProperty "prop_unfoldr" prop_unfoldr+ , testProperty "prop_unfoldr1" prop_unfoldr1+ , testProperty "prop_unfoldrN" prop_unfoldrN+ , testProperty "prop_unfoldr1N" prop_unfoldr1N+ , testProperty "prop_unfoldrM" prop_unfoldrM+ , testProperty "prop_unfoldr1M" prop_unfoldr1M+ , testProperty "prop_unfoldrNM" prop_unfoldrNM+ , testProperty "prop_unfoldr1NM" prop_unfoldr1NM+ , testProperty "prop_constructN" prop_constructN+ , testProperty "prop_constructrN" prop_constructrN+ ]+ , testGroup "Enumeration"+ [ testProperty "prop_enumFromN" prop_enumFromN+ , testProperty "prop_enumFromN1" prop_enumFromN1+ , testProperty "prop_enumFromStepN" prop_enumFromStepN+ , testProperty "prop_enumFromStepN1" prop_enumFromStepN1+ , testProperty "prop_enumFromTo" prop_enumFromTo+ , testProperty "prop_enumFromThenTo" prop_enumFromThenTo+ ]+ , testGroup "Concatenation"+ [ testProperty "prop_cons" prop_cons+ , testProperty "prop_consV" prop_consV+ , testProperty "prop_snoc" prop_snoc+ , testProperty "prop_snocV" prop_snocV+ , testProperty "prop_append" prop_append+ , testProperty "prop_concat" prop_concat+ , testProperty "prop_concat1" prop_concat1+ ]+ , testGroup "Restricting memory usage"+ [ testProperty "prop_force" prop_force+ ]+ ]++-- ---------------------------------------------------------------------- --+-- Initialization++prop_singleton :: Int -> Property+prop_singleton a = elemsU (NEV.singleton a) === [a]++prop_replicate :: Int -> Int -> Property+prop_replicate n a =+ fmap elemsU (NEV.replicate n a) === whenNonEmpty (List.replicate n a)++prop_replicate1 :: Int -> Int -> Property+prop_replicate1 n a =+ elemsU (NEV.replicate1 n a) === List.replicate (max n 1) a++prop_generate :: Int -> Fun Int Int -> Property+prop_generate n (Fn f) =+ fmap elemsU (NEV.generate n f) === whenNonEmpty (fmap f [0 .. n - 1])++prop_generate1 :: Int -> Fun Int Int -> Property+prop_generate1 n (Fn f) =+ elemsU (NEV.generate1 n f) === fmap f [0 .. max n 1 - 1]++prop_iterateN :: Int -> Fun Int Int -> Int -> Property+prop_iterateN n (Fn f) a =+ fmap elemsU (NEV.iterateN n f a)+ === whenNonEmpty (List.take n (List.iterate f a))++prop_iterateN1 :: Int -> Fun Int Int -> Int -> Property+prop_iterateN1 n (Fn f) a =+ elemsU (NEV.iterateN1 n f a) === List.take (max n 1) (List.iterate f a)++-- ---------------------------------------------------------------------- --+-- Monadic initialization++prop_replicateM :: Int -> Int -> Property+prop_replicateM n a =+ fmap (fmap elemsU) (NEV.replicateM n (logged () a))+ === (List.replicate n (), whenNonEmpty (List.replicate n a))++prop_replicate1M :: Int -> Int -> Property+prop_replicate1M n a =+ fmap elemsU (NEV.replicate1M n (logged () a))+ === (List.replicate n' (), List.replicate n' a)+ where+ n' = max n 1++prop_generateM :: Int -> Fun Int Int -> Property+prop_generateM n (Fn f) =+ fmap (fmap elemsU) (NEV.generateM n (\i -> logged i (f i)))+ === (is, whenNonEmpty (fmap f is))+ where+ is = [0 .. n - 1]++prop_generate1M :: Int -> Fun Int Int -> Property+prop_generate1M n (Fn f) =+ fmap elemsU (NEV.generate1M n (\i -> logged i (f i)))+ === (is, fmap f is)+ where+ is = [0 .. max n 1 - 1]++-- The step function runs once per element after the seed.+prop_iterateNM :: Int -> Fun Int Int -> Int -> Property+prop_iterateNM n (Fn f) a =+ fmap (fmap elemsU) (NEV.iterateNM n (\b -> logged b (f b)) a)+ === (List.take (n - 1) as, whenNonEmpty (List.take n as))+ where+ as = List.iterate f a++prop_iterateN1M :: Int -> Fun Int Int -> Int -> Property+prop_iterateN1M n (Fn f) a =+ fmap elemsU (NEV.iterateN1M n (\b -> logged b (f b)) a)+ === (List.take (n' - 1) as, List.take n' as)+ where+ n' = max n 1+ as = List.iterate f a++prop_create :: [Int] -> Property+prop_create as =+ fmap elemsU (NEV.create (V.thaw (V.fromList as))) === whenNonEmpty as++prop_unsafeCreate :: NonEmptyUVector Int -> Property+prop_unsafeCreate v =+ elemsU (NEV.unsafeCreate (V.thaw (V.fromList (elemsU v)))) === elemsU v++prop_createT :: [[Int]] -> Property+prop_createT ass =+ fmap (fmap elemsU) (NEV.createT (traverse (V.thaw . V.fromList) ass))+ === fmap whenNonEmpty ass++prop_unsafeCreateT :: [NonEmptyUVector Int] -> Property+prop_unsafeCreateT vs =+ fmap elemsU (NEV.unsafeCreateT (traverse (V.thaw . V.fromList . elemsU) vs))+ === fmap elemsU vs++-- ---------------------------------------------------------------------- --+-- Unfolding++prop_unfoldr :: Fun Int Int -> Int -> Property+prop_unfoldr (Fn f) b =+ fmap elemsU (NEV.unfoldr (unfoldStep f) b)+ === whenNonEmpty (List.unfoldr (unfoldStep f) b)++prop_unfoldr1 :: Fun Int Int -> Int -> Int -> Property+prop_unfoldr1 (Fn f) a b =+ elemsU (NEV.unfoldr1 (unfoldStep f) a b)+ === a : List.unfoldr (unfoldStep f) b++prop_unfoldrN :: Int -> Fun Int Int -> Int -> Property+prop_unfoldrN n (Fn f) b =+ fmap elemsU (NEV.unfoldrN n (unfoldStep f) b)+ === whenNonEmpty (List.take n (List.unfoldr (unfoldStep f) b))++-- The initial element is supplied in addition to at most @n@ unfolded ones.+prop_unfoldr1N :: Int -> Fun Int Int -> Int -> Int -> Property+prop_unfoldr1N n (Fn f) a b =+ elemsU (NEV.unfoldr1N n (unfoldStep f) a b)+ === a : List.take n (List.unfoldr (unfoldStep f) b)++prop_unfoldrM :: Fun Int Int -> Int -> Property+prop_unfoldrM (Fn f) b =+ fmap (fmap elemsU) (NEV.unfoldrM step b)+ === fmap whenNonEmpty (unfoldrMList step b)+ where+ step s = logged s (unfoldStep f s)++prop_unfoldr1M :: Fun Int Int -> Int -> Int -> Property+prop_unfoldr1M (Fn f) a b =+ fmap elemsU (NEV.unfoldr1M step a b) === fmap (a :) (unfoldrMList step b)+ where+ step s = logged s (unfoldStep f s)++prop_unfoldrNM :: Int -> Fun Int Int -> Int -> Property+prop_unfoldrNM n (Fn f) b =+ fmap (fmap elemsU) (NEV.unfoldrNM n step b)+ === fmap whenNonEmpty (unfoldrNMList n step b)+ where+ step s = logged s (unfoldStep f s)++prop_unfoldr1NM :: Int -> Fun Int Int -> Int -> Int -> Property+prop_unfoldr1NM n (Fn f) a b =+ fmap elemsU (NEV.unfoldr1NM n step a b)+ === fmap (a :) (unfoldrNMList n step b)+ where+ step s = logged s (unfoldStep f s)++-- Each element is generated from the prefix constructed so far.+prop_constructN :: Fun [Int] Int -> Property+prop_constructN (Fn f) = forAll (choose (0, 30)) $ \n ->+ fmap elemsU (NEV.constructN n (f . V.toList))+ === whenNonEmpty (construct n [])+ where+ construct n acc+ | List.length acc >= n = acc+ | otherwise = construct n (acc ++ [f acc])++-- Each element is generated from the suffix constructed so far.+prop_constructrN :: Fun [Int] Int -> Property+prop_constructrN (Fn f) = forAll (choose (0, 30)) $ \n ->+ fmap elemsU (NEV.constructrN n (f . V.toList))+ === whenNonEmpty (construct n [])+ where+ construct n acc+ | List.length acc >= n = acc+ | otherwise = construct n (f acc : acc)++-- ---------------------------------------------------------------------- --+-- Enumeration++prop_enumFromN :: Int -> Int -> Property+prop_enumFromN a n =+ fmap elemsU (NEV.enumFromN a n) === whenNonEmpty (fmap (a +) [0 .. n - 1])++prop_enumFromN1 :: Int -> Int -> Property+prop_enumFromN1 a n =+ elemsU (NEV.enumFromN1 a n) === fmap (a +) [0 .. max n 1 - 1]++prop_enumFromStepN :: Int -> Int -> Int -> Property+prop_enumFromStepN a s n =+ fmap elemsU (NEV.enumFromStepN a s n)+ === whenNonEmpty [ a + s * i | i <- [0 .. n - 1] ]++prop_enumFromStepN1 :: Int -> Int -> Int -> Property+prop_enumFromStepN1 a s n =+ elemsU (NEV.enumFromStepN1 a s n) === [ a + s * i | i <- [0 .. max n 1 - 1] ]++prop_enumFromTo :: Int -> Int -> Property+prop_enumFromTo a b = fmap elemsU (NEV.enumFromTo a b) === whenNonEmpty [a .. b]++-- A zero step would enumerate forever.+prop_enumFromThenTo :: Int -> Int -> Int -> Property+prop_enumFromThenTo a b c = a /= b ==>+ fmap elemsU (NEV.enumFromThenTo a b c) === whenNonEmpty [a, b .. c]++-- ---------------------------------------------------------------------- --+-- Concatenation++prop_cons :: Int -> NonEmptyUVector Int -> Property+prop_cons a v = elemsU (NEV.cons a v) === a : elemsU v++prop_consV :: Int -> [Int] -> Property+prop_consV a as = elemsU (NEV.consV a (V.fromList as)) === a : as++prop_snoc :: NonEmptyUVector Int -> Int -> Property+prop_snoc v a = elemsU (NEV.snoc v a) === elemsU v ++ [a]++prop_snocV :: [Int] -> Int -> Property+prop_snocV as a = elemsU (NEV.snocV (V.fromList as) a) === as ++ [a]++prop_append :: NonEmptyUVector Int -> NonEmptyUVector Int -> Property+prop_append v w = elemsU (v NEV.++ w) === elemsU v ++ elemsU w++prop_concat :: [NonEmptyUVector Int] -> Property+prop_concat vs =+ fmap elemsU (NEV.concat vs) === whenNonEmpty (List.concatMap elemsU vs)++prop_concat1 :: NonEmptyUVector Int -> [NonEmptyUVector Int] -> Property+prop_concat1 v vs =+ elemsU (NEV.concat1 (v :| vs)) === List.concatMap elemsU (v : vs)++-- ---------------------------------------------------------------------- --+-- Restricting memory usage++prop_force :: NonEmptyUVector Int -> Property+prop_force v = forAll (genSliceU v) $ \(i, m) -> m > 0 ==>+ let w = NonEmptyUVector (V.slice i m (_neUvec v))+ in elemsU (NEV.force w) === List.take m (List.drop i (elemsU v))
+ test/Test/Data/Vector/NonEmpty/ConversionU.hs view
@@ -0,0 +1,115 @@+-- |+-- Module : Test.Data.Vector.NonEmpty.ConversionU+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Properties for conversions to and from non-empty lists, vectors, and+-- lists.+--+module Test.Data.Vector.NonEmpty.ConversionU+( tests+) where+++import qualified Data.List as List+import Data.List.NonEmpty (NonEmpty(..))+import qualified Data.Vector.Unboxed as V+import Data.Vector.NonEmpty.Unboxed (NonEmptyUVector)+import qualified Data.Vector.NonEmpty.Unboxed as NEV++import Test.Data.Vector.NonEmpty.Util+import Test.QuickCheck+import Test.Tasty+import Test.Tasty.QuickCheck+++tests :: TestTree+tests = testGroup "Conversion"+ [ testGroup "To/from non-empty lists"+ [ testProperty "prop_toNonEmpty" prop_toNonEmpty+ , testProperty "prop_fromNonEmpty" prop_fromNonEmpty+ , testProperty "prop_from_to_nonempty" prop_from_to_nonempty+ , testProperty "prop_fromNonEmptyN" prop_fromNonEmptyN+ , testProperty "prop_fromNonEmptyN1" prop_fromNonEmptyN1+ , testProperty "prop_unsafeFromList" prop_unsafeFromList+ ]+ , testGroup "To/from vector"+ [ testProperty "prop_toVector" prop_toVector+ , testProperty "prop_fromVector" prop_fromVector+ , testProperty "prop_unsafeFromVector" prop_unsafeFromVector+ , testProperty "prop_from_to_vec" prop_from_to_vec+ ]+ , testGroup "To/from list"+ [ testProperty "prop_toList" prop_toList+ , testProperty "prop_fromList" prop_fromList+ , testProperty "prop_fromListN" prop_fromListN+ , testProperty "prop_from_to_list" prop_from_to_list+ ]+ ]++-- ---------------------------------------------------------------------- --+-- To/from non-empty lists++prop_toNonEmpty :: NonEmptyUVector Int -> Property+prop_toNonEmpty v = NEV.toNonEmpty v === elems1U v++prop_fromNonEmpty :: Int -> [Int] -> Property+prop_fromNonEmpty a as = elemsU (NEV.fromNonEmpty (a :| as)) === a : as++prop_from_to_nonempty :: NonEmptyUVector Int -> Property+prop_from_to_nonempty v = NEV.fromNonEmpty (NEV.toNonEmpty v) === v++prop_fromNonEmptyN :: Int -> Int -> [Int] -> Property+prop_fromNonEmptyN n a as =+ fmap elemsU (NEV.fromNonEmptyN n (a :| as))+ === whenNonEmpty (List.take n (a : as))++prop_fromNonEmptyN1 :: Int -> Int -> [Int] -> Property+prop_fromNonEmptyN1 n a as =+ elemsU (NEV.fromNonEmptyN1 n (a :| as)) === List.take (max n 1) (a : as)++prop_unsafeFromList :: NonEmptyList Int -> Property+prop_unsafeFromList (NonEmpty as) = elemsU (NEV.unsafeFromList as) === as++-- ---------------------------------------------------------------------- --+-- To/from vector++prop_toVector :: NonEmptyUVector Int -> Property+prop_toVector v = V.toList (NEV.toVector v) === elemsU v++prop_fromVector :: [Int] -> Property+prop_fromVector as =+ fmap elemsU (NEV.fromVector (V.fromList as)) === whenNonEmpty as++prop_unsafeFromVector :: NonEmptyList Int -> Property+prop_unsafeFromVector (NonEmpty as) =+ elemsU (NEV.unsafeFromVector (V.fromList as)) === as++prop_from_to_vec :: NonEmptyUVector Int -> NonEmptyList Int -> Property+prop_from_to_vec t (NonEmpty as) =+ NEV.fromVector (NEV.toVector t) === Just t+ .&&. (NEV.toVector <$> NEV.fromVector u) === Just u+ where+ u = V.fromList as++-- ---------------------------------------------------------------------- --+-- To/from list++prop_toList :: NonEmptyUVector Int -> Property+prop_toList v = NEV.toList v === elemsU v++prop_fromList :: [Int] -> Property+prop_fromList as = fmap elemsU (NEV.fromList as) === whenNonEmpty as++prop_fromListN :: Int -> [Int] -> Property+prop_fromListN n as =+ fmap elemsU (NEV.fromListN n as) === whenNonEmpty (List.take n as)++prop_from_to_list :: NonEmptyUVector Int -> NonEmptyList Int -> Property+prop_from_to_list t (NonEmpty u) =+ NEV.fromList (NEV.toList t) === Just t+ .&&. fmap NEV.toList (NEV.fromList u) === Just u
+ test/Test/Data/Vector/NonEmpty/ElementwiseU.hs view
@@ -0,0 +1,288 @@+-- |+-- Module : Test.Data.Vector.NonEmpty.ElementwiseU+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Properties for indexing, mapping, zipping, and unzipping.+--+-- Monadic operations run in a writer-style @([w], -)@ monad so that the+-- order and number of effects are observable.+--+module Test.Data.Vector.NonEmpty.ElementwiseU+( tests+) where+++import qualified Data.List as List+import Data.Vector.NonEmpty.Unboxed (NonEmptyUVector)+import qualified Data.Vector.NonEmpty.Unboxed as NEV++import Test.Data.Vector.NonEmpty.Util+import Test.QuickCheck+import Test.Tasty+import Test.Tasty.QuickCheck+++tests :: TestTree+tests = testGroup "Elementwise"+ [ testGroup "Indexing"+ [ testProperty "prop_indexed" prop_indexed+ ]+ , testGroup "Mapping"+ [ testProperty "prop_map" prop_map+ , testProperty "prop_imap" prop_imap+ , testProperty "prop_concatMap" prop_concatMap+ ]+ , testGroup "Monadic mapping"+ [ testProperty "prop_mapM" prop_mapM+ , testProperty "prop_imapM" prop_imapM+ , testProperty "prop_mapM_" prop_mapM_+ , testProperty "prop_imapM_" prop_imapM_+ , testProperty "prop_forM" prop_forM+ , testProperty "prop_forM_" prop_forM_+ ]+ , testGroup "Zipping"+ [ testProperty "prop_zipWith" prop_zipWith+ , testProperty "prop_zipWith3" prop_zipWith3+ {-+ , testProperty "prop_zipWith4" prop_zipWith4+ , testProperty "prop_zipWith5" prop_zipWith5+ , testProperty "prop_zipWith6" prop_zipWith6+ , testProperty "prop_izipWith" prop_izipWith+ , testProperty "prop_izipWith3" prop_izipWith3+ , testProperty "prop_izipWith4" prop_izipWith4+ , testProperty "prop_izipWith5" prop_izipWith5+ , testProperty "prop_izipWith6" prop_izipWith6+ -}+ , testProperty "prop_zip" prop_zip+ , testProperty "prop_zip3" prop_zip3+ , testProperty "prop_zip4" prop_zip4+ , testProperty "prop_zip5" prop_zip5+ , testProperty "prop_zip6" prop_zip6+ ]+ , testGroup "Monadic zipping"+ [ testProperty "prop_zipWithM" prop_zipWithM+ , testProperty "prop_zipWithM_" prop_zipWithM_+ , testProperty "prop_izipWithM" prop_izipWithM+ , testProperty "prop_izipWithM_" prop_izipWithM_+ ]+ , testGroup "Unzipping"+ [ testProperty "prop_unzip" prop_unzip+ , testProperty "prop_unzip3" prop_unzip3+ , testProperty "prop_unzip4" prop_unzip4+ , testProperty "prop_unzip5" prop_unzip5+ , testProperty "prop_unzip6" prop_unzip6+ ]+ ]++type V = NonEmptyUVector Int++-- ---------------------------------------------------------------------- --+-- Indexing++prop_indexed :: V -> Property+prop_indexed v = elemsU (NEV.indexed v) === List.zip [0 ..] (elemsU v)++-- ---------------------------------------------------------------------- --+-- Mapping++prop_map :: Fun Int Int -> V -> Property+prop_map (Fn f) v = elemsU (NEV.map f v) === List.map f (elemsU v)++prop_imap :: Fun (Int, Int) Int -> V -> Property+prop_imap (Fn2 f) v = elemsU (NEV.imap f v) === List.zipWith f [0 ..] (elemsU v)++prop_concatMap :: Fun Int V -> V -> Property+prop_concatMap (Fn f) v =+ elemsU (NEV.concatMap f v) === List.concatMap (elemsU . f) (elemsU v)++-- ---------------------------------------------------------------------- --+-- Monadic mapping++prop_mapM :: Fun Int Int -> V -> Property+prop_mapM (Fn f) v =+ fmap elemsU (NEV.mapM (\a -> logged a (f a)) v)+ === (elemsU v, List.map f (elemsU v))++prop_imapM :: Fun (Int, Int) Int -> V -> Property+prop_imapM (Fn2 f) v =+ fmap elemsU (NEV.imapM (\i a -> logged i (f i a)) v)+ === (is, List.zipWith f is (elemsU v))+ where+ is = [0 .. NEV.length v - 1]++prop_mapM_ :: V -> Property+prop_mapM_ v = NEV.mapM_ (\a -> logged a a) v === (elemsU v, ())++prop_imapM_ :: V -> Property+prop_imapM_ v =+ NEV.imapM_ (\i a -> logged (i, a) a) v+ === (List.zip [0 ..] (elemsU v), ())++prop_forM :: Fun Int Int -> V -> Property+prop_forM (Fn f) v =+ fmap elemsU (NEV.forM v (\a -> logged a (f a)))+ === (elemsU v, List.map f (elemsU v))++prop_forM_ :: V -> Property+prop_forM_ v = NEV.forM_ v (\a -> logged a a) === (elemsU v, ())++-- ---------------------------------------------------------------------- --+-- Zipping+--+-- The higher arities collect their arguments in order, so the models+-- detect both truncation to the shortest input and argument order.++prop_zipWith :: Fun (Int, Int) Int -> V -> V -> Property+prop_zipWith (Fn2 f) a b =+ elemsU (NEV.zipWith f a b) === List.zipWith f (elemsU a) (elemsU b)++prop_zipWith3 :: Fun (Int, Int, Int) Int -> V -> V -> V -> Property+prop_zipWith3 (Fn3 f) a b c =+ elemsU (NEV.zipWith3 f a b c)+ === List.zipWith3 f (elemsU a) (elemsU b) (elemsU c)++{-+prop_zipWith4 :: V -> V -> V -> V -> Property+prop_zipWith4 a b c d =+ elemsU (NEV.zipWith4 k a b c d)+ === List.zipWith4 k (elemsU a) (elemsU b) (elemsU c) (elemsU d)+ where+ k p q r s = [p, q, r, s]++prop_zipWith5 :: V -> V -> V -> V -> V -> Property+prop_zipWith5 a b c d e =+ elemsU (NEV.zipWith5 k a b c d e)+ === List.zipWith5 k (elemsU a) (elemsU b) (elemsU c) (elemsU d) (elemsU e)+ where+ k p q r s t = [p, q, r, s, t]++prop_zipWith6 :: V -> V -> V -> V -> V -> V -> Property+prop_zipWith6 a b c d e f =+ elemsU (NEV.zipWith6 k a b c d e f)+ === List.zipWith6 k+ (elemsU a) (elemsU b) (elemsU c) (elemsU d) (elemsU e) (elemsU f)+ where+ k p q r s t u = [p, q, r, s, t, u]++prop_izipWith :: V -> V -> Property+prop_izipWith a b =+ elemsU (NEV.izipWith k a b) === List.zipWith3 k [0 ..] (elemsU a) (elemsU b)+ where+ k i p q = [i, p, q]++prop_izipWith3 :: V -> V -> V -> Property+prop_izipWith3 a b c =+ elemsU (NEV.izipWith3 k a b c)+ === List.zipWith4 k [0 ..] (elemsU a) (elemsU b) (elemsU c)+ where+ k i p q r = [i, p, q, r]++prop_izipWith4 :: V -> V -> V -> V -> Property+prop_izipWith4 a b c d =+ elemsU (NEV.izipWith4 k a b c d)+ === List.zipWith5 k [0 ..] (elemsU a) (elemsU b) (elemsU c) (elemsU d)+ where+ k i p q r s = [i, p, q, r, s]++prop_izipWith5 :: V -> V -> V -> V -> V -> Property+prop_izipWith5 a b c d e =+ elemsU (NEV.izipWith5 k a b c d e)+ === List.zipWith6 k [0 ..]+ (elemsU a) (elemsU b) (elemsU c) (elemsU d) (elemsU e)+ where+ k i p q r s t = [i, p, q, r, s, t]++prop_izipWith6 :: V -> V -> V -> V -> V -> V -> Property+prop_izipWith6 a b c d e f =+ elemsU (NEV.izipWith6 k a b c d e f)+ === List.zipWith7 k [0 ..]+ (elemsU a) (elemsU b) (elemsU c) (elemsU d) (elemsU e) (elemsU f)+ where+ k i p q r s t u = [i, p, q, r, s, t, u]+-}++prop_zip :: V -> V -> Property+prop_zip a b = elemsU (NEV.zip a b) === List.zip (elemsU a) (elemsU b)++prop_zip3 :: V -> V -> V -> Property+prop_zip3 a b c =+ elemsU (NEV.zip3 a b c) === List.zip3 (elemsU a) (elemsU b) (elemsU c)++prop_zip4 :: V -> V -> V -> V -> Property+prop_zip4 a b c d =+ elemsU (NEV.zip4 a b c d)+ === List.zip4 (elemsU a) (elemsU b) (elemsU c) (elemsU d)++prop_zip5 :: V -> V -> V -> V -> V -> Property+prop_zip5 a b c d e =+ elemsU (NEV.zip5 a b c d e)+ === List.zip5 (elemsU a) (elemsU b) (elemsU c) (elemsU d) (elemsU e)++prop_zip6 :: V -> V -> V -> V -> V -> V -> Property+prop_zip6 a b c d e f =+ elemsU (NEV.zip6 a b c d e f)+ === List.zip6 (elemsU a) (elemsU b) (elemsU c) (elemsU d) (elemsU e) (elemsU f)++-- ---------------------------------------------------------------------- --+-- Monadic zipping++prop_zipWithM :: Fun (Int, Int) Int -> V -> V -> Property+prop_zipWithM (Fn2 f) a b =+ fmap elemsU (NEV.zipWithM (\p q -> logged (p, q) (f p q)) a b)+ === (ps, List.map (uncurry f) ps)+ where+ ps = List.zip (elemsU a) (elemsU b)++prop_zipWithM_ :: V -> V -> Property+prop_zipWithM_ a b =+ NEV.zipWithM_ (\p q -> logged (p, q) p) a b+ === (List.zip (elemsU a) (elemsU b), ())++prop_izipWithM :: Fun (Int, Int, Int) Int -> V -> V -> Property+prop_izipWithM (Fn3 f) a b =+ fmap elemsU (NEV.izipWithM (\i p q -> logged i (f i p q)) a b)+ === (List.map fst ips, List.map (\(i, (p, q)) -> f i p q) ips)+ where+ ips = List.zip [0 ..] (List.zip (elemsU a) (elemsU b))++prop_izipWithM_ :: V -> V -> Property+prop_izipWithM_ a b =+ NEV.izipWithM_ (\i p q -> logged (i, p, q) p) a b+ === (List.zip3 [0 ..] (elemsU a) (elemsU b), ())++-- ---------------------------------------------------------------------- --+-- Unzipping++prop_unzip :: NonEmptyUVector (Int, Int) -> Property+prop_unzip v = (elemsU a, elemsU b) === List.unzip (elemsU v)+ where+ (a, b) = NEV.unzip v++prop_unzip3 :: NonEmptyUVector (Int, Int, Int) -> Property+prop_unzip3 v = (elemsU a, elemsU b, elemsU c) === List.unzip3 (elemsU v)+ where+ (a, b, c) = NEV.unzip3 v++prop_unzip4 :: NonEmptyUVector (Int, Int, Int, Int) -> Property+prop_unzip4 v =+ (elemsU a, elemsU b, elemsU c, elemsU d) === List.unzip4 (elemsU v)+ where+ (a, b, c, d) = NEV.unzip4 v++prop_unzip5 :: NonEmptyUVector (Int, Int, Int, Int, Int) -> Property+prop_unzip5 v =+ (elemsU a, elemsU b, elemsU c, elemsU d, elemsU e) === List.unzip5 (elemsU v)+ where+ (a, b, c, d, e) = NEV.unzip5 v++prop_unzip6 :: NonEmptyUVector (Int, Int, Int, Int, Int, Int) -> Property+prop_unzip6 v =+ (elemsU a, elemsU b, elemsU c, elemsU d, elemsU e, elemsU f)+ === List.unzip6 (elemsU v)+ where+ (a, b, c, d, e, f) = NEV.unzip6 v
+ test/Test/Data/Vector/NonEmpty/FoldsU.hs view
@@ -0,0 +1,285 @@+-- |+-- Module : Test.Data.Vector.NonEmpty.FoldsU+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Properties for folds, specialized folds, monadic folds, and sequencing.+--+-- Fold functions are arbitrary, hence neither associative nor commutative,+-- so the models pin down fold direction and argument order. Monadic folds+-- run in a writer-style @([w], -)@ monad to expose effect order.+--+module Test.Data.Vector.NonEmpty.FoldsU+( tests+) where+++import qualified Control.Monad as Monad+import qualified Data.List as List+import Data.List.NonEmpty (NonEmpty(..))+import Data.Ord (comparing)+import Data.Vector.NonEmpty.Unboxed (NonEmptyUVector)+import qualified Data.Vector.NonEmpty.Unboxed as NEV++import Test.Data.Vector.NonEmpty.Util+import Test.QuickCheck+import Test.Tasty+import Test.Tasty.QuickCheck+++tests :: TestTree+tests = testGroup "Folds (unboxed)"+ [ testGroup "Folding"+ [ testProperty "prop_foldl" prop_foldl+ , testProperty "prop_foldl1" prop_foldl1+ , testProperty "prop_foldl'" prop_foldl'+ , testProperty "prop_foldl1'" prop_foldl1'+ , testProperty "prop_foldr" prop_foldr+ , testProperty "prop_foldr1" prop_foldr1+ , testProperty "prop_foldr'" prop_foldr'+ , testProperty "prop_foldr1'" prop_foldr1'+ , testProperty "prop_ifoldl" prop_ifoldl+ , testProperty "prop_ifoldl'" prop_ifoldl'+ , testProperty "prop_ifoldr" prop_ifoldr+ , testProperty "prop_ifoldr'" prop_ifoldr'+ ]+ , testGroup "Specialized folds"+ [ testProperty "prop_all" prop_all+ , testProperty "prop_any" prop_any+ , testProperty "prop_and" prop_and+ , testProperty "prop_or" prop_or+ , testProperty "prop_sum" prop_sum+ , testProperty "prop_product" prop_product+ , testProperty "prop_maximum" prop_maximum+ , testProperty "prop_maximumBy" prop_maximumBy+ , testProperty "prop_minimum" prop_minimum+ , testProperty "prop_minimumBy" prop_minimumBy+ , testProperty "prop_maxIndex" prop_maxIndex+ , testProperty "prop_maxIndexBy" prop_maxIndexBy+ , testProperty "prop_minIndex" prop_minIndex+ , testProperty "prop_minIndexBy" prop_minIndexBy+ ]+ , testGroup "Monadic folds"+ [ testProperty "prop_foldM" prop_foldM+ , testProperty "prop_foldM'" prop_foldM'+ , testProperty "prop_fold1M" prop_fold1M+ , testProperty "prop_fold1M'" prop_fold1M'+ , testProperty "prop_foldM_" prop_foldM_+ , testProperty "prop_foldM'_" prop_foldM'_+ , testProperty "prop_fold1M_" prop_fold1M_+ , testProperty "prop_fold1M'_" prop_fold1M'_+ , testProperty "prop_ifoldM" prop_ifoldM+ , testProperty "prop_ifoldM'" prop_ifoldM'+ , testProperty "prop_ifoldM_" prop_ifoldM_+ , testProperty "prop_ifoldM'_" prop_ifoldM'_+ ]+ ]++type V = NonEmptyUVector Int++-- ---------------------------------------------------------------------- --+-- Models++indexedList :: V -> [(Int, Int)]+indexedList = List.zip [0 ..] . elemsU++-- | Ties resolve to the first occurrence, matching @vector@.+--+firstBy :: (a -> a -> Bool) -> [(Int, a)] -> (Int, a)+firstBy better = List.foldl1 (\x y -> if better (snd y) (snd x) then y else x)++-- | A comparison with many ties, so that tie-breaking is exercised.+--+coarse :: Int -> Int -> Ordering+coarse = comparing (`mod` 3)++-- | A writer-style step that logs the accumulator and element it consumes,+-- exposing how the accumulator is threaded even when the result is+-- discarded.+--+step :: (Int -> Int -> Int) -> Int -> Int -> ([(Int, Int)], Int)+step f acc a = logged (acc, a) (f acc a)++-- | A writer-style indexed step that logs the accumulator and index it+-- consumes.+--+istep+ :: (Int -> Int -> Int -> Int)+ -> Int+ -> Int+ -> Int+ -> ([(Int, Int)], Int)+istep f acc i a = logged (acc, i) (f acc i a)++-- ---------------------------------------------------------------------- --+-- Folding++prop_foldl :: Fun (Int, Int) Int -> Int -> V -> Property+prop_foldl (Fn2 f) z v = NEV.foldl f z v === List.foldl f z (elemsU v)++prop_foldl1 :: Fun (Int, Int) Int -> V -> Property+prop_foldl1 (Fn2 f) v = NEV.foldl1 f v === foldl1 f (elems1U v)++prop_foldl' :: Fun (Int, Int) Int -> Int -> V -> Property+prop_foldl' (Fn2 f) z v = NEV.foldl' f z v === List.foldl f z (elemsU v)++prop_foldl1' :: Fun (Int, Int) Int -> V -> Property+prop_foldl1' (Fn2 f) v = NEV.foldl1' f v === foldl1 f (elems1U v)++prop_foldr :: Fun (Int, Int) Int -> Int -> V -> Property+prop_foldr (Fn2 f) z v = NEV.foldr f z v === List.foldr f z (elemsU v)++prop_foldr1 :: Fun (Int, Int) Int -> V -> Property+prop_foldr1 (Fn2 f) v = NEV.foldr1 f v === foldr1 f (elems1U v)++prop_foldr' :: Fun (Int, Int) Int -> Int -> V -> Property+prop_foldr' (Fn2 f) z v = NEV.foldr' f z v === List.foldr f z (elemsU v)++prop_foldr1' :: Fun (Int, Int) Int -> V -> Property+prop_foldr1' (Fn2 f) v = NEV.foldr1' f v === foldr1 f (elems1U v)++prop_ifoldl :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_ifoldl (Fn3 f) z v =+ NEV.ifoldl f z v+ === List.foldl (\acc (i, a) -> f acc i a) z (indexedList v)++prop_ifoldl' :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_ifoldl' (Fn3 f) z v =+ NEV.ifoldl' f z v+ === List.foldl (\acc (i, a) -> f acc i a) z (indexedList v)++prop_ifoldr :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_ifoldr (Fn3 f) z v =+ NEV.ifoldr f z v+ === List.foldr (\(i, a) acc -> f i a acc) z (indexedList v)++prop_ifoldr' :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_ifoldr' (Fn3 f) z v =+ NEV.ifoldr' f z v+ === List.foldr (\(i, a) acc -> f i a acc) z (indexedList v)++-- ---------------------------------------------------------------------- --+-- Specialized folds++prop_all :: Fun Int Bool -> V -> Property+prop_all (Fn p) v = NEV.all p v === List.all p (elemsU v)++prop_any :: Fun Int Bool -> V -> Property+prop_any (Fn p) v = NEV.any p v === List.any p (elemsU v)++prop_and :: NonEmptyUVector Bool -> Property+prop_and v = NEV.and v === List.and (elemsU v)++prop_or :: NonEmptyUVector Bool -> Property+prop_or v = NEV.or v === List.or (elemsU v)++prop_sum :: V -> Property+prop_sum v = NEV.sum v === List.sum (elemsU v)++prop_product :: V -> Property+prop_product v = NEV.product v === List.product (elemsU v)++prop_maximum :: V -> Property+prop_maximum v = NEV.maximum v === maximum (elems1U v)++prop_maximumBy :: V -> Property+prop_maximumBy v =+ NEV.maximumBy coarse v+ === snd (firstBy (\a b -> coarse a b == GT) (indexedList v))++prop_minimum :: V -> Property+prop_minimum v = NEV.minimum v === minimum (elems1U v)++prop_minimumBy :: V -> Property+prop_minimumBy v =+ NEV.minimumBy coarse v+ === snd (firstBy (\a b -> coarse a b == LT) (indexedList v))++prop_maxIndex :: V -> Property+prop_maxIndex v =+ NEV.maxIndex w === fst (firstBy (>) (indexedList w))+ where+ w = vecU (List.map (`mod` 4) (elemsU v))++prop_maxIndexBy :: V -> Property+prop_maxIndexBy v =+ NEV.maxIndexBy coarse v+ === fst (firstBy (\a b -> coarse a b == GT) (indexedList v))++prop_minIndex :: V -> Property+prop_minIndex v =+ NEV.minIndex w === fst (firstBy (<) (indexedList w))+ where+ w = vecU (List.map (`mod` 4) (elemsU v))++prop_minIndexBy :: V -> Property+prop_minIndexBy v =+ NEV.minIndexBy coarse v+ === fst (firstBy (\a b -> coarse a b == LT) (indexedList v))++-- ---------------------------------------------------------------------- --+-- Monadic folds++prop_foldM :: Fun (Int, Int) Int -> Int -> V -> Property+prop_foldM (Fn2 f) z v =+ NEV.foldM (step f) z v === Monad.foldM (step f) z (elemsU v)++prop_foldM' :: Fun (Int, Int) Int -> Int -> V -> Property+prop_foldM' (Fn2 f) z v =+ NEV.foldM' (step f) z v === Monad.foldM (step f) z (elemsU v)++prop_fold1M :: Fun (Int, Int) Int -> V -> Property+prop_fold1M (Fn2 f) v =+ NEV.fold1M (step f) v === Monad.foldM (step f) a as+ where+ a :| as = elems1U v++prop_fold1M' :: Fun (Int, Int) Int -> V -> Property+prop_fold1M' (Fn2 f) v =+ NEV.fold1M' (step f) v === Monad.foldM (step f) a as+ where+ a :| as = elems1U v++prop_foldM_ :: Fun (Int, Int) Int -> Int -> V -> Property+prop_foldM_ (Fn2 f) z v =+ NEV.foldM_ (step f) z v === Monad.foldM_ (step f) z (elemsU v)++prop_foldM'_ :: Fun (Int, Int) Int -> Int -> V -> Property+prop_foldM'_ (Fn2 f) z v =+ NEV.foldM'_ (step f) z v === Monad.foldM_ (step f) z (elemsU v)++prop_fold1M_ :: Fun (Int, Int) Int -> V -> Property+prop_fold1M_ (Fn2 f) v =+ NEV.fold1M_ (step f) v === Monad.foldM_ (step f) a as+ where+ a :| as = elems1U v++prop_fold1M'_ :: Fun (Int, Int) Int -> V -> Property+prop_fold1M'_ (Fn2 f) v =+ NEV.fold1M'_ (step f) v === Monad.foldM_ (step f) a as+ where+ a :| as = elems1U v++prop_ifoldM :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_ifoldM (Fn3 f) z v =+ NEV.ifoldM (istep f) z v+ === Monad.foldM (\acc (i, a) -> istep f acc i a) z (indexedList v)++prop_ifoldM' :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_ifoldM' (Fn3 f) z v =+ NEV.ifoldM' (istep f) z v+ === Monad.foldM (\acc (i, a) -> istep f acc i a) z (indexedList v)++prop_ifoldM_ :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_ifoldM_ (Fn3 f) z v =+ NEV.ifoldM_ (istep f) z v+ === Monad.foldM_ (\acc (i, a) -> istep f acc i a) z (indexedList v)++prop_ifoldM'_ :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_ifoldM'_ (Fn3 f) z v =+ NEV.ifoldM'_ (istep f) z v+ === Monad.foldM_ (\acc (i, a) -> istep f acc i a) z (indexedList v)
+ test/Test/Data/Vector/NonEmpty/GroupingU.hs view
@@ -0,0 +1,107 @@+module Test.Data.Vector.NonEmpty.GroupingU+( tests+) where+++import qualified Data.List as List+import qualified Data.List.NonEmpty as NonEmpty+import Data.Vector.NonEmpty.Unboxed (NonEmptyUVector)+import Data.Vector.Unboxed (Unbox)+import qualified Data.Vector.NonEmpty.Unboxed as NEV++import Test.Data.Vector.NonEmpty.Util+import Test.QuickCheck+import Test.Tasty+import Test.Tasty.QuickCheck+++tests :: TestTree+tests = testGroup "Grouping (unboxed)"+ [ testGroup "group"+ [ testProperty "prop_group" prop_group+ , testProperty "prop_group_singleton" prop_group_singleton+ , testProperty "prop_group_all_equal" prop_group_all_equal+ , testProperty "prop_group_distinct" prop_group_distinct+ , testProperty "prop_group_runs" prop_group_runs+ ]+ , testGroup "groupBy"+ [ testProperty "prop_groupBy" prop_groupBy+ , testProperty "prop_groupBy_singleton" prop_groupBy_singleton+ , testProperty "prop_groupBy_all_true" prop_groupBy_all_true+ , testProperty "prop_groupBy_all_false" prop_groupBy_all_false+ , testProperty "prop_groupBy_equivalence" prop_groupBy_equivalence+ , testProperty "prop_groupBy_nontransitive" prop_groupBy_nontransitive+ , testProperty "prop_groupBy_asymmetric" prop_groupBy_asymmetric+ ]+ ]++groupElems :: Unbox element => NonEmpty.NonEmpty (NonEmptyUVector element) -> [[element]]+groupElems = List.map elemsU . NonEmpty.toList++prop_group :: NonEmptyUVector Int -> Property+prop_group input =+ groupElems (NEV.group (vecU values)) === List.group values+ where+ values = List.map (`mod` 4) (elemsU input)++prop_group_singleton :: Int -> Property+prop_group_singleton value =+ groupElems (NEV.group (vecU [value])) === [[value]]++prop_group_all_equal :: Int -> Positive Int -> Property+prop_group_all_equal value (Positive count) =+ groupElems (NEV.group (vecU values)) === [values]+ where+ values = List.replicate count value++prop_group_distinct :: NonEmptyUVector Int -> Property+prop_group_distinct input =+ groupElems (NEV.group (vecU values)) === List.map (: []) values+ where+ values = List.nub (elemsU input)++prop_group_runs :: Property+prop_group_runs = once $+ groupElems (NEV.group (vecU "Mississippi"))+ === ["M", "i", "ss", "i", "ss", "i", "pp", "i"]++prop_groupBy :: Fun (Int, Int) Bool -> NonEmptyUVector Int -> Property+prop_groupBy (Fn2 predicate) input =+ groupElems (NEV.groupBy predicate (vecU values))+ === List.groupBy predicate values+ where+ values = List.map (`mod` 4) (elemsU input)++prop_groupBy_singleton :: Int -> Property+prop_groupBy_singleton value =+ groupElems (NEV.groupBy predicate (vecU [value])) === [[value]]+ where+ predicate _ _ = error "groupBy evaluated its predicate on a singleton"++prop_groupBy_all_true :: NonEmptyUVector Int -> Property+prop_groupBy_all_true input =+ groupElems (NEV.groupBy (\_ _ -> True) input) === [elemsU input]++prop_groupBy_all_false :: NonEmptyUVector Int -> Property+prop_groupBy_all_false input =+ groupElems (NEV.groupBy (\_ _ -> False) input)+ === List.map (: []) (elemsU input)++prop_groupBy_equivalence :: NonEmptyUVector Int -> Property+prop_groupBy_equivalence input =+ groupElems (NEV.groupBy sameParity input)+ === List.groupBy sameParity (elemsU input)+ where+ sameParity first second = even first == even second++prop_groupBy_nontransitive :: Property+prop_groupBy_nontransitive = once $+ groupElems (NEV.groupBy nearby (vecU [1, 2, 3, 4] :: NonEmptyUVector Int))+ === [[1, 2], [3, 4]]+ where+ nearby first second = abs (first - second) <= 1++prop_groupBy_asymmetric :: Property+prop_groupBy_asymmetric = once $+ groupElems (NEV.groupBy (<) (vecU [1, 2, 1, 3, 0, 4] :: NonEmptyUVector Int))+ === [[1, 2], [1, 3], [0, 4]]
+ test/Test/Data/Vector/NonEmpty/InstancesU.hs view
@@ -0,0 +1,142 @@+-- |+-- Module : Test.Data.Vector.NonEmpty.InstancesU+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Laws and list models for the type class instances of t'NonEmptyUVector'.+--+module Test.Data.Vector.NonEmpty.InstancesU+( tests+) where+++import Control.DeepSeq (rnf)+import Control.Exception (evaluate)++import Data.Data (gmapM, gmapQ, gmapT, showConstr, toConstr)+import qualified Data.List as List+import Data.List.NonEmpty (NonEmpty(..))+import Data.Semigroup (sconcat, stimes)+import Data.Vector.NonEmpty.Unboxed (NonEmptyUVector)+import qualified Data.Vector.NonEmpty.Unboxed as NEV++import Test.Data.Vector.NonEmpty.Util+import Test.QuickCheck+import Test.Tasty+import Test.Tasty.QuickCheck++import Text.Read (readMaybe)+++tests :: TestTree+tests = testGroup "Instances (unboxed)"+ [ testGroup "Eq"+ [ testProperty "prop_eq" prop_eq+ ]+ , testGroup "Ord"+ [ testProperty "prop_compare" prop_compare+ ]+ , testGroup "Show"+ [ testProperty "prop_show" prop_show+ , testProperty "prop_showsPrec" prop_showsPrec+ ]+ , testGroup "Read"+ [ testProperty "prop_read_show" prop_read_show+ , testProperty "prop_read_list" prop_read_list+ ]+ , testGroup "Semigroup"+ [ testProperty "prop_append" prop_append+ , testProperty "prop_semigroup_associativity" prop_semigroup_associativity+ , testProperty "prop_sconcat" prop_sconcat+ , testProperty "prop_stimes" prop_stimes+ , testProperty "prop_stimes_non_positive" prop_stimes_non_positive+ ]+ , testGroup "NFData"+ [ testProperty "prop_rnf" prop_rnf+ , testProperty "prop_rnf_forces_elements" prop_rnf_forces_elements+ ]+ , testGroup "Data"+ [ testProperty "prop_data" prop_data+ ]+ ]++type V = NonEmptyUVector Int++-- | Either the same vector or an unrelated one, so that equal pairs are+-- generated often.+--+genNear :: V -> Gen V+genNear v = oneof [pure v, arbitrary]++-- ---------------------------------------------------------------------- --+-- Eq and Ord++prop_eq :: V -> Property+prop_eq v = forAll (genNear v) $ \w -> (v == w) === (elemsU v == elemsU w)++prop_compare :: V -> Property+prop_compare v = forAll (genNear v) $ \w ->+ compare v w === compare (elemsU v) (elemsU w)++-- ---------------------------------------------------------------------- --+-- Show and Read++prop_show :: V -> Property+prop_show v = show v === show (elemsU v)++prop_showsPrec :: Int -> V -> String -> Property+prop_showsPrec d v s = showsPrec d v s === show (elemsU v) ++ s++prop_read_show :: V -> Property+prop_read_show v = read (show v) === v++-- The empty list must not parse.+prop_read_list :: [Int] -> Property+prop_read_list as =+ fmap elemsU (readMaybe (show as) :: Maybe V) === whenNonEmpty as++-- ---------------------------------------------------------------------- --+-- Semigroup++prop_append :: V -> V -> Property+prop_append v w = elemsU (v <> w) === elemsU v ++ elemsU w++prop_semigroup_associativity :: V -> V -> V -> Property+prop_semigroup_associativity u v w = ((u <> v) <> w) === (u <> (v <> w))++prop_sconcat :: V -> [V] -> Property+prop_sconcat v vs = elemsU (sconcat (v :| vs)) === List.concatMap elemsU (v : vs)++prop_stimes :: V -> Property+prop_stimes v = forAll (choose (1, 5)) $ \n ->+ elemsU (stimes (n :: Int) v) === List.concat (List.replicate n (elemsU v))++-- A non-positive multiplier would produce an empty vector, so it must throw.+prop_stimes_non_positive :: V -> Property+prop_stimes_non_positive v = forAll (choose (-5, 0)) $ \n ->+ throws (stimes (n :: Int) v)++-- ---------------------------------------------------------------------- --+-- NFData++prop_rnf :: V -> Property+prop_rnf v = rnf v === ()++prop_rnf_forces_elements :: Property+prop_rnf_forces_elements = once $+ throwsIO (evaluate (rnf (NEV.singleton (error "unforced element" :: Int))))++-- ---------------------------------------------------------------------- --+-- Data++-- The representation is a single constructor wrapping a single field.+prop_data :: V -> Property+prop_data v =+ gmapT id v === v+ .&&. gmapM Just v === Just v+ .&&. gmapQ (const ()) v === [()]+ .&&. showConstr (toConstr v) === "NonEmptyUVector"
+ test/Test/Data/Vector/NonEmpty/ModificationU.hs view
@@ -0,0 +1,184 @@+-- |+-- Module : Test.Data.Vector.NonEmpty.ModificationU+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Properties for bulk updates, accumulations, permutations, and safe+-- destructive updates.+--+module Test.Data.Vector.NonEmpty.ModificationU+( tests+) where+++import qualified Data.List as List+import Data.Maybe (mapMaybe)+import qualified Data.Vector.Unboxed as V+import qualified Data.Vector.Unboxed.Mutable as MV+import Data.Vector.NonEmpty.Unboxed (NonEmptyUVector)+import qualified Data.Vector.NonEmpty.Unboxed as NEV++import Test.Data.Vector.NonEmpty.Util+import Test.QuickCheck+import Test.Tasty+import Test.Tasty.QuickCheck+++tests :: TestTree+tests = testGroup "Modification (unboxed)"+ [ testGroup "Bulk updates"+ [ testProperty "prop_bulk_update" prop_bulk_update+ , testProperty "prop_bulk_update_out_of_bounds" prop_bulk_update_out_of_bounds+ , testProperty "prop_update" prop_update+ , testProperty "prop_update_" prop_update_+ , testProperty "prop_unsafeUpd" prop_unsafeUpd+ , testProperty "prop_unsafeUpdate" prop_unsafeUpdate+ , testProperty "prop_unsafeUpdate_" prop_unsafeUpdate_+ ]+ , testGroup "Accumulations"+ [ testProperty "prop_accum" prop_accum+ , testProperty "prop_accum_out_of_bounds" prop_accum_out_of_bounds+ , testProperty "prop_accumulate" prop_accumulate+ , testProperty "prop_accumulate_" prop_accumulate_+ , testProperty "prop_unsafeAccum" prop_unsafeAccum+ , testProperty "prop_unsafeAccumulate" prop_unsafeAccumulate+ , testProperty "prop_unsafeAccumulate_" prop_unsafeAccumulate_+ ]+ , testGroup "Permutations"+ [ testProperty "prop_reverse" prop_reverse+ , testProperty "prop_reverse_involutive" prop_reverse_involutive+ , testProperty "prop_backpermute" prop_backpermute+ , testProperty "prop_backpermute_out_of_bounds" prop_backpermute_out_of_bounds+ , testProperty "prop_unsafeBackpermute" prop_unsafeBackpermute+ ]+ , testGroup "Safe destructive updates"+ [ testProperty "prop_modify" prop_modify+ , testProperty "prop_modify_preserves_input" prop_modify_preserves_input+ ]+ ]++-- ---------------------------------------------------------------------- --+-- Models++-- | Later updates to the same index win.+--+updateList :: [(Int, a)] -> [a] -> [a]+updateList us as = List.foldl' (\acc (i, a) -> adjustAt i (const a) acc) as us++accumList :: (a -> b -> a) -> [(Int, b)] -> [a] -> [a]+accumList f us as = List.foldl' (\acc (i, b) -> adjustAt i (`f` b) acc) as us++-- ---------------------------------------------------------------------- --+-- Bulk updates++prop_bulk_update :: NonEmptyUVector Int -> Property+prop_bulk_update v = forAll (genUpdatesU v) $ \us ->+ elemsU (v NEV.// us) === updateList us (elemsU v)++prop_bulk_update_out_of_bounds :: NonEmptyUVector Int -> Int -> Property+prop_bulk_update_out_of_bounds v a = forAll (genOutOfBoundsU v) $ \i ->+ throws (v NEV.// [(i, a)])++prop_update :: NonEmptyUVector Int -> Property+prop_update v = forAll (genUpdatesU v) $ \us ->+ elemsU (NEV.update v (V.fromList us)) === updateList us (elemsU v)++-- Surplus values beyond the index vector are ignored.+prop_update_ :: NonEmptyUVector Int -> [Int] -> Property+prop_update_ v surplus = forAll (genUpdatesU v) $ \us ->+ let (is, as) = List.unzip us+ in elemsU (NEV.update_ v (V.fromList is) (V.fromList (as ++ surplus)))+ === updateList us (elemsU v)++prop_unsafeUpd :: NonEmptyUVector Int -> Property+prop_unsafeUpd v = forAll (genUpdatesU v) $ \us ->+ elemsU (NEV.unsafeUpd v us) === updateList us (elemsU v)++prop_unsafeUpdate :: NonEmptyUVector Int -> Property+prop_unsafeUpdate v = forAll (genUpdatesU v) $ \us ->+ elemsU (NEV.unsafeUpdate v (V.fromList us)) === updateList us (elemsU v)++prop_unsafeUpdate_ :: NonEmptyUVector Int -> Property+prop_unsafeUpdate_ v = forAll (genUpdatesU v) $ \us ->+ let (is, as) = List.unzip us+ in elemsU (NEV.unsafeUpdate_ v (V.fromList is) (V.fromList as))+ === updateList us (elemsU v)++-- ---------------------------------------------------------------------- --+-- Accumulations++prop_accum :: Fun (Int, Int) Int -> NonEmptyUVector Int -> Property+prop_accum (Fn2 f) v = forAll (genUpdatesU v) $ \us ->+ elemsU (NEV.accum f v us) === accumList f us (elemsU v)++prop_accum_out_of_bounds :: NonEmptyUVector Int -> Int -> Property+prop_accum_out_of_bounds v b = forAll (genOutOfBoundsU v) $ \i ->+ throws (NEV.accum (+) v [(i, b)])++prop_accumulate :: Fun (Int, Int) Int -> NonEmptyUVector Int -> Property+prop_accumulate (Fn2 f) v = forAll (genUpdatesU v) $ \us ->+ elemsU (NEV.accumulate f v (V.fromList us)) === accumList f us (elemsU v)++prop_accumulate_ :: Fun (Int, Int) Int -> NonEmptyUVector Int -> Property+prop_accumulate_ (Fn2 f) v = forAll (genUpdatesU v) $ \us ->+ let (is, bs) = List.unzip us+ in elemsU (NEV.accumulate_ f v (V.fromList is) (V.fromList bs))+ === accumList f us (elemsU v)++prop_unsafeAccum :: Fun (Int, Int) Int -> NonEmptyUVector Int -> Property+prop_unsafeAccum (Fn2 f) v = forAll (genUpdatesU v) $ \us ->+ elemsU (NEV.unsafeAccum f v us) === accumList f us (elemsU v)++prop_unsafeAccumulate :: Fun (Int, Int) Int -> NonEmptyUVector Int -> Property+prop_unsafeAccumulate (Fn2 f) v = forAll (genUpdatesU v) $ \us ->+ elemsU (NEV.unsafeAccumulate f v (V.fromList us))+ === accumList f us (elemsU v)++prop_unsafeAccumulate_ :: Fun (Int, Int) Int -> NonEmptyUVector Int -> Property+prop_unsafeAccumulate_ (Fn2 f) v = forAll (genUpdatesU v) $ \us ->+ let (is, bs) = List.unzip us+ in elemsU (NEV.unsafeAccumulate_ f v (V.fromList is) (V.fromList bs))+ === accumList f us (elemsU v)++-- ---------------------------------------------------------------------- --+-- Permutations++prop_reverse :: NonEmptyUVector Int -> Property+prop_reverse v = elemsU (NEV.reverse v) === List.reverse (elemsU v)++prop_reverse_involutive :: NonEmptyUVector Int -> Property+prop_reverse_involutive v = NEV.reverse (NEV.reverse v) === v++prop_backpermute :: NonEmptyUVector Int -> Property+prop_backpermute v = forAll (genIndicesU v) $ \is ->+ elemsU (NEV.backpermute v is)+ === mapMaybe (`lookupList` elemsU v) (elemsU is)++prop_backpermute_out_of_bounds :: NonEmptyUVector Int -> Property+prop_backpermute_out_of_bounds v = forAll (genOutOfBoundsU v) $ \i ->+ throws (NEV.backpermute v (NEV.singleton i))++prop_unsafeBackpermute :: NonEmptyUVector Int -> Property+prop_unsafeBackpermute v = forAll (genIndicesU v) $ \is ->+ elemsU (NEV.unsafeBackpermute v is)+ === mapMaybe (`lookupList` elemsU v) (elemsU is)++-- ---------------------------------------------------------------------- --+-- Safe destructive updates++prop_modify :: NonEmptyUVector Int -> Int -> Property+prop_modify v a = forAll ((,) <$> genIndexU v <*> genIndexU v) $ \(i, j) ->+ elemsU (NEV.modify (\mv -> MV.write mv i a >> MV.swap mv i j) v)+ === swapAt i j (adjustAt i (const a) (elemsU v))++-- The input vector is copied, never mutated in place.+prop_modify_preserves_input :: NonEmptyList Int -> Int -> Property+prop_modify_preserves_input (NonEmpty as) a =+ (elemsU w, elemsU v) === (List.map (const a) as, as)+ where+ v = vecU as+ w = NEV.modify (`MV.set` a) v
+ test/Test/Data/Vector/NonEmpty/MutableU.hs view
@@ -0,0 +1,440 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeApplications #-}+-- |+-- Module : Test.Data.Vector.NonEmpty.MutableU+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Properties for non-empty mutable vectors, observed by freezing them+-- into lists.+--+module Test.Data.Vector.NonEmpty.MutableU+( tests+) where+++import Control.Monad.ST (ST, runST)++import qualified Data.List as List+import qualified Data.List.NonEmpty as NonEmpty+import Data.STRef (modifySTRef', newSTRef, readSTRef)+import qualified Data.Vector.Unboxed as V+import Data.Vector.Unboxed.Mutable (MVector)+import qualified Data.Vector.Unboxed.Mutable as MV+import Data.Vector.NonEmpty.Unboxed.Internal+ ( NonEmptyMUVector(..)+ , NonEmptyUVector(..)+ , NonEmptyIOUVector+ , NonEmptySTUVector+ )+import qualified Data.Vector.NonEmpty.Unboxed.Mutable as NEMV++import Test.Data.Vector.NonEmpty.Util+import Test.QuickCheck+import Test.Tasty+import Test.Tasty.QuickCheck+++tests :: TestTree+tests = testGroup "Mutable (unboxed)"+ [ testGroup "Length information"+ [ testProperty "prop_length" prop_length+ ]+ , testGroup "Extracting subvectors"+ [ testProperty "prop_slice" prop_slice+ , testProperty "prop_slice_shares" prop_slice_shares+ , testProperty "prop_init" prop_init+ , testProperty "prop_tail" prop_tail+ , testProperty "prop_take" prop_take+ , testProperty "prop_drop" prop_drop+ , testProperty "prop_splitAt" prop_splitAt+ , testProperty "prop_unsafeSlice" prop_unsafeSlice+ , testProperty "prop_unsafeTake" prop_unsafeTake+ , testProperty "prop_unsafeDrop" prop_unsafeDrop+ ]+ , testGroup "Overlapping"+ [ testProperty "prop_overlaps_self" prop_overlaps_self+ , testProperty "prop_overlaps_distinct" prop_overlaps_distinct+ , testProperty "prop_overlaps_slices" prop_overlaps_slices+ ]+ , testGroup "Conversions"+ [ testProperty "prop_fromMVector" prop_fromMVector+ , testProperty "prop_toMVector" prop_toMVector+ , testProperty "prop_unsafeFromMVector" prop_unsafeFromMVector+ ]+ , testGroup "Initialisation"+ [ testProperty "prop_new" prop_new+ , testProperty "prop_new1" prop_new1+ , testProperty "prop_unsafeNew" prop_unsafeNew+ , testProperty "prop_replicate" prop_replicate+ , testProperty "prop_replicate1" prop_replicate1+ , testProperty "prop_replicateM" prop_replicateM+ , testProperty "prop_replicate1M" prop_replicate1M+ , testProperty "prop_clone" prop_clone+ ]+ , testGroup "Growing"+ [ testProperty "prop_grow" prop_grow+ , testProperty "prop_grow_negative" prop_grow_negative+ , testProperty "prop_unsafeGrow" prop_unsafeGrow+ ]+ , testGroup "Accessing individual elements"+ [ testProperty "prop_read" prop_read+ , testProperty "prop_read_out_of_bounds" prop_read_out_of_bounds+ , testProperty "prop_write" prop_write+ , testProperty "prop_write_out_of_bounds" prop_write_out_of_bounds+ , testProperty "prop_modify" prop_modify+ , testProperty "prop_swap" prop_swap+ , testProperty "prop_unsafeRead" prop_unsafeRead+ , testProperty "prop_unsafeWrite" prop_unsafeWrite+ , testProperty "prop_unsafeModify" prop_unsafeModify+ , testProperty "prop_unsafeSwap" prop_unsafeSwap+ ]+ , testGroup "Modifying vectors"+ [ testProperty "prop_nextPermutation" prop_nextPermutation+ , testProperty "prop_nextPermutation_last" prop_nextPermutation_last+ ]+ , testGroup "Filling and copying"+ [ testProperty "prop_set" prop_set+ , testProperty "prop_copy" prop_copy+ , testProperty "prop_copy_length_mismatch" prop_copy_length_mismatch+ , testProperty "prop_unsafeCopy" prop_unsafeCopy+ , testProperty "prop_move" prop_move+ , testProperty "prop_unsafeMove" prop_unsafeMove+ ]+ ]++type V = NonEmptyUVector Int++-- ---------------------------------------------------------------------- --+-- Running mutable vectors++thaw :: V.Unbox a => NonEmptyUVector a -> ST s (NonEmptySTUVector s a)+thaw = fmap NonEmptyMUVector . V.thaw . _neUvec++thawIO :: V.Unbox a => NonEmptyUVector a -> IO (NonEmptyIOUVector a)+thawIO = fmap NonEmptyMUVector . V.thaw . _neUvec++-- | Run a computation against a fresh mutable copy of the vector.+--+withThawed :: V.Unbox a => NonEmptyUVector a -> (forall s. NonEmptySTUVector s a -> ST s b) -> b+withThawed v k = runST (thaw v >>= k)++freezeList :: V.Unbox a => MVector s a -> ST s [a]+freezeList = fmap V.toList . V.freeze++freeze :: V.Unbox a => NonEmptySTUVector s a -> ST s [a]+freeze = freezeList . _nemUvec++-- | A mutable operation's effect on the vector's contents.+--+mutated :: V -> (forall s. NonEmptySTUVector s Int -> ST s ()) -> [Int]+mutated v k = withThawed v (\mv -> k mv >> freeze mv)++-- ---------------------------------------------------------------------- --+-- Length information++prop_length :: V -> Property+prop_length v = withThawed v (pure . NEMV.length) === List.length (elemsU v)++-- ---------------------------------------------------------------------- --+-- Extracting subvectors++prop_slice :: V -> Property+prop_slice v = forAll (genSliceU v) $ \(i, m) ->+ withThawed v (freezeList . NEMV.slice i m)+ === List.take m (List.drop i (elemsU v))++-- Subvectors are views: writes through them reach the parent vector.+prop_slice_shares :: V -> Int -> Property+prop_slice_shares v a = forAll (genIndexU v) $ \i ->+ mutated v (\mv -> MV.write (NEMV.drop i mv) 0 a)+ === adjustAt i (const a) (elemsU v)++prop_init :: V -> Property+prop_init v =+ withThawed v (freezeList . NEMV.init)+ === List.take (List.length (elemsU v) - 1) (elemsU v)++prop_tail :: V -> Property+prop_tail v = withThawed v (freezeList . NEMV.tail) === List.drop 1 (elemsU v)++prop_take :: Int -> V -> Property+prop_take n v =+ withThawed v (freezeList . NEMV.take n) === List.take n (elemsU v)++prop_drop :: Int -> V -> Property+prop_drop n v =+ withThawed v (freezeList . NEMV.drop n) === List.drop n (elemsU v)++prop_splitAt :: Int -> V -> Property+prop_splitAt n v =+ withThawed v (\mv -> let (as, bs) = NEMV.splitAt n mv+ in (,) <$> freezeList as <*> freezeList bs)+ === List.splitAt n (elemsU v)++prop_unsafeSlice :: V -> Property+prop_unsafeSlice v = forAll (genSliceU v) $ \(i, m) ->+ withThawed v (freezeList . NEMV.unsafeSlice i m)+ === List.take m (List.drop i (elemsU v))++prop_unsafeTake :: V -> Property+prop_unsafeTake v = forAll (choose (0, List.length (elemsU v))) $ \n ->+ withThawed v (freezeList . NEMV.unsafeTake n) === List.take n (elemsU v)++prop_unsafeDrop :: V -> Property+prop_unsafeDrop v = forAll (choose (0, List.length (elemsU v))) $ \n ->+ withThawed v (freezeList . NEMV.unsafeDrop n) === List.drop n (elemsU v)++-- ---------------------------------------------------------------------- --+-- Overlapping++prop_overlaps_self :: V -> Property+prop_overlaps_self v = withThawed v (\mv -> pure (NEMV.overlaps mv mv)) === True++prop_overlaps_distinct :: V -> V -> Property+prop_overlaps_distinct v w = runST (NEMV.overlaps <$> thaw v <*> thaw w) === False++-- Adjacent slices are disjoint; extending one by an element overlaps them.+prop_overlaps_slices :: V -> Property+prop_overlaps_slices v = n >= 2 ==> forAll (choose (1, n - 1)) $ \k ->+ withThawed v (\(NonEmptyMUVector mv) ->+ let front m = NonEmptyMUVector (MV.take m mv)+ back = NonEmptyMUVector (MV.drop k mv)+ in pure (NEMV.overlaps (front k) back, NEMV.overlaps (front (k + 1)) back))+ === (False, True)+ where+ n = List.length (elemsU v)++-- ---------------------------------------------------------------------- --+-- Conversions++prop_fromMVector :: [Int] -> Property+prop_fromMVector as =+ runST (V.thaw (V.fromList as) >>= traverse freeze . NEMV.fromMVector)+ === whenNonEmpty as++prop_toMVector :: V -> Property+prop_toMVector v = withThawed v (freezeList . NEMV.toMVector) === elemsU v++prop_unsafeFromMVector :: V -> Property+prop_unsafeFromMVector v =+ runST (V.thaw (_neUvec v) >>= freeze . NEMV.unsafeFromMVector) === elemsU v++-- ---------------------------------------------------------------------- --+-- Initialisation++prop_new :: NonNegative Int -> Property+prop_new (NonNegative n) =+ runST (fmap NEMV.length <$> NEMV.new @_ @Int n)+ === if n > 0 then Just n else Nothing++prop_new1 :: Int -> Property+prop_new1 n = runST (NEMV.length <$> NEMV.new1 @_ @Int n) === max n 1++prop_unsafeNew :: NonNegative Int -> Property+prop_unsafeNew (NonNegative n) =+ runST (fmap NEMV.length <$> NEMV.unsafeNew @_ @Int n)+ === if n > 0 then Just n else Nothing++prop_replicate :: Int -> Int -> Property+prop_replicate n a =+ runST (NEMV.replicate n a >>= traverse freeze)+ === whenNonEmpty (List.replicate n a)++prop_replicate1 :: Int -> Int -> Property+prop_replicate1 n a =+ runST (NEMV.replicate1 n a >>= freeze) === List.replicate (max n 1) a++-- The action runs once per element, in order.+prop_replicateM :: Int -> Property+prop_replicateM n =+ runST (counter >>= NEMV.replicateM n >>= traverse freeze)+ === whenNonEmpty [1 .. n]++prop_replicate1M :: Int -> Property+prop_replicate1M n =+ runST (counter >>= NEMV.replicate1M n >>= traverse freeze)+ === Just [1 .. max n 1]++-- | An action yielding 1, 2, 3, ... on successive runs.+--+counter :: ST s (ST s Int)+counter = do+ ref <- newSTRef 0+ pure (modifySTRef' ref (+ 1) >> readSTRef ref)++-- A clone has the same contents but no longer aliases the original.+prop_clone :: V -> Int -> Property+prop_clone v a =+ withThawed v (\mv -> do+ c <- NEMV.clone mv+ MV.set (_nemUvec c) a+ (,) <$> freeze mv <*> freeze c)+ === (elemsU v, List.map (const a) (elemsU v))++-- ---------------------------------------------------------------------- --+-- Growing++prop_grow :: V -> NonNegative Int -> Property+prop_grow v (NonNegative n) =+ withThawed v (\mv -> do+ g <- NEMV.grow mv n+ as <- freezeList (MV.take (NEMV.length mv) (_nemUvec g))+ pure (NEMV.length g, as))+ === (List.length (elemsU v) + n, elemsU v)++prop_grow_negative :: V -> Positive Int -> Property+prop_grow_negative v (Positive n) =+ throwsIO (thawIO v >>= \mv -> NEMV.grow mv (negate n))++prop_unsafeGrow :: V -> NonNegative Int -> Property+prop_unsafeGrow v (NonNegative n) =+ withThawed v (\mv -> do+ g <- NEMV.unsafeGrow mv n+ as <- freezeList (MV.take (NEMV.length mv) (_nemUvec g))+ pure (NEMV.length g, as))+ === (List.length (elemsU v) + n, elemsU v)++-- ---------------------------------------------------------------------- --+-- Accessing individual elements++prop_read :: V -> Property+prop_read v = forAll (genIndexU v) $ \i ->+ Just (withThawed v (`NEMV.read` i)) === lookupList i (elemsU v)++prop_read_out_of_bounds :: V -> Property+prop_read_out_of_bounds v = forAll (genOutOfBoundsU v) $ \i ->+ throwsIO (thawIO v >>= (`NEMV.read` i))++prop_write :: V -> Int -> Property+prop_write v a = forAll (genIndexU v) $ \i ->+ mutated v (\mv -> NEMV.write mv i a) === adjustAt i (const a) (elemsU v)++prop_write_out_of_bounds :: V -> Int -> Property+prop_write_out_of_bounds v a = forAll (genOutOfBoundsU v) $ \i ->+ throwsIO (thawIO v >>= \mv -> NEMV.write mv i a)++prop_modify :: Fun Int Int -> V -> Property+prop_modify (Fn f) v = forAll (genIndexU v) $ \i ->+ mutated v (\mv -> NEMV.modify mv f i) === adjustAt i f (elemsU v)++prop_swap :: V -> Property+prop_swap v = forAll ((,) <$> genIndexU v <*> genIndexU v) $ \(i, j) ->+ mutated v (\mv -> NEMV.swap mv i j) === swapAt i j (elemsU v)++prop_unsafeRead :: V -> Property+prop_unsafeRead v = forAll (genIndexU v) $ \i ->+ Just (withThawed v (`NEMV.unsafeRead` i)) === lookupList i (elemsU v)++prop_unsafeWrite :: V -> Int -> Property+prop_unsafeWrite v a = forAll (genIndexU v) $ \i ->+ mutated v (\mv -> NEMV.unsafeWrite mv i a) === adjustAt i (const a) (elemsU v)++prop_unsafeModify :: Fun Int Int -> V -> Property+prop_unsafeModify (Fn f) v = forAll (genIndexU v) $ \i ->+ mutated v (\mv -> NEMV.unsafeModify mv f i) === adjustAt i f (elemsU v)++prop_unsafeSwap :: V -> Property+prop_unsafeSwap v = forAll ((,) <$> genIndexU v <*> genIndexU v) $ \(i, j) ->+ mutated v (\mv -> NEMV.unsafeSwap mv i j) === swapAt i j (elemsU v)++-- ---------------------------------------------------------------------- --+-- Modifying vectors++-- Starting from sorted order, successive permutations enumerate every+-- distinct permutation in lexicographic order.+prop_nextPermutation :: Property+prop_nextPermutation =+ forAll (choose (1, 5)) $ \n ->+ forAll (vectorOf n (choose (0, 3))) $ \as ->+ let sorted = List.sort (as :: [Int])+ in withThawed (vecU sorted) enumerate+ === List.map NonEmpty.head+ (NonEmpty.group (List.sort (List.permutations sorted)))+ where+ enumerate :: NonEmptySTUVector s Int -> ST s [[Int]]+ enumerate mv = do+ as <- freeze mv+ more <- NEMV.nextPermutation mv+ if more then (as :) <$> enumerate mv else pure [as]++-- The last permutation has no successor and is left unchanged.+prop_nextPermutation_last :: V -> Property+prop_nextPermutation_last v =+ withThawed (vecU descending) (\mv -> (,) <$> NEMV.nextPermutation mv <*> freeze mv)+ === (False, descending)+ where+ descending = List.sortBy (flip compare) (elemsU v)++-- ---------------------------------------------------------------------- --+-- Filling and copying++prop_set :: V -> Int -> Property+prop_set v a =+ mutated v (`NEMV.set` a) === List.map (const a) (elemsU v)++-- | Copy @v@ over a vector of the same length, returning the target and+-- source contents afterwards.+--+copied+ :: (forall s. NonEmptySTUVector s Int -> NonEmptySTUVector s Int -> ST s ())+ -> V+ -> [Int]+ -> ([Int], [Int])+copied cp v bs = runST $ do+ dst <- thaw (vecU bs)+ src <- thaw v+ cp dst src+ (,) <$> freeze dst <*> freeze src++prop_copy :: V -> Property+prop_copy v = forAll (vectorOf (List.length (elemsU v)) arbitrary) $ \bs ->+ copied NEMV.copy v bs === (elemsU v, elemsU v)++prop_copy_length_mismatch :: V -> Property+prop_copy_length_mismatch v = throwsIO $ do+ dst <- thawIO (vecU (0 : elemsU v))+ src <- thawIO v+ NEMV.copy dst src++prop_unsafeCopy :: V -> Property+prop_unsafeCopy v = forAll (vectorOf (List.length (elemsU v)) arbitrary) $ \bs ->+ copied NEMV.unsafeCopy v bs === (elemsU v, elemsU v)++-- | Move between the overlapping slices @[0, n - 1)@ and @[1, n)@ of one+-- vector, in both directions.+--+moved+ :: (forall s. NonEmptySTUVector s Int -> NonEmptySTUVector s Int -> ST s ())+ -> V+ -> ([Int], [Int])+moved mv v = (shift True, shift False)+ where+ n = List.length (elemsU v)++ shift left = withThawed v $ \(NonEmptyMUVector raw) -> do+ let lo = NonEmptyMUVector (MV.slice 0 (n - 1) raw)+ hi = NonEmptyMUVector (MV.slice 1 (n - 1) raw)+ if left then mv lo hi else mv hi lo+ freezeList raw++prop_move :: V -> Property+prop_move v = List.length as >= 2 ==>+ moved NEMV.move v+ === (List.drop 1 as ++ List.drop (n - 1) as, List.take 1 as ++ List.take (n - 1) as)+ where+ as = elemsU v+ n = List.length as++prop_unsafeMove :: V -> Property+prop_unsafeMove v = List.length as >= 2 ==>+ moved NEMV.unsafeMove v+ === (List.drop 1 as ++ List.drop (n - 1) as, List.take 1 as ++ List.take (n - 1) as)+ where+ as = elemsU v+ n = List.length as
+ test/Test/Data/Vector/NonEmpty/PredicatesU.hs view
@@ -0,0 +1,192 @@+-- |+-- Module : Test.Data.Vector.NonEmpty.PredicatesU+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Properties for filtering, partitioning, and searching.+--+-- Elements are reduced modulo a small number where duplicates or hits+-- need to be likely.+--+module Test.Data.Vector.NonEmpty.PredicatesU+( tests+) where+++import Data.Either (partitionEithers)+import qualified Data.List as List+import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Maybe as Maybe+import qualified Data.Vector.Unboxed as V+import Data.Vector.NonEmpty.Unboxed (NonEmptyUVector)+import qualified Data.Vector.NonEmpty.Unboxed as NEV++import Test.Data.Vector.NonEmpty.Util+import Test.QuickCheck+import Test.Tasty+import Test.Tasty.QuickCheck+++tests :: TestTree+tests = testGroup "Predicates (unboxed)"+ [ testGroup "Filtering"+ [ testProperty "prop_uniq" prop_uniq+ , testProperty "prop_mapMaybe" prop_mapMaybe+ , testProperty "prop_imapMaybe" prop_imapMaybe+ , testProperty "prop_filter" prop_filter+ , testProperty "prop_ifilter" prop_ifilter+ , testProperty "prop_filterM" prop_filterM+ , testProperty "prop_ifilterM" prop_ifilterM+ , testProperty "prop_takeWhile" prop_takeWhile+ , testProperty "prop_dropWhile" prop_dropWhile+ ]+ , testGroup "Partitioning"+ [ testProperty "prop_partition" prop_partition+ , testProperty "prop_partitionWith" prop_partitionWith+ , testProperty "prop_unstablePartition" prop_unstablePartition+ , testProperty "prop_span" prop_span+ , testProperty "prop_break" prop_break+ ]+ , testGroup "Searching"+ [ testProperty "prop_elem" prop_elem+ , testProperty "prop_notElem" prop_notElem+ , testProperty "prop_find" prop_find+ , testProperty "prop_findIndex" prop_findIndex+ , testProperty "prop_findIndices" prop_findIndices+ , testProperty "prop_elemIndex" prop_elemIndex+ , testProperty "prop_elemIndices" prop_elemIndices+ ]+ ]++type V = NonEmptyUVector Int++-- | Reduce elements to a small range so that duplicates and matches are+-- common.+--+small :: V -> V+small = vecU . List.map (`mod` 4) . elemsU++-- ---------------------------------------------------------------------- --+-- Filtering++prop_uniq :: V -> Property+prop_uniq v =+ elemsU (NEV.uniq w) === List.map NonEmpty.head (NonEmpty.group (elemsU w))+ where+ w = small v++prop_mapMaybe :: Fun Int (Maybe Int) -> V -> Property+prop_mapMaybe (Fn f) v =+ V.toList (NEV.mapMaybe f v) === Maybe.mapMaybe f (elemsU v)++prop_imapMaybe :: Fun (Int, Int) (Maybe Int) -> V -> Property+prop_imapMaybe (Fn2 f) v =+ V.toList (NEV.imapMaybe f v)+ === Maybe.catMaybes (List.zipWith f [0 ..] (elemsU v))++prop_filter :: Fun Int Bool -> V -> Property+prop_filter (Fn p) v = V.toList (NEV.filter p v) === List.filter p (elemsU v)++prop_ifilter :: Fun (Int, Int) Bool -> V -> Property+prop_ifilter (Fn2 p) v =+ V.toList (NEV.ifilter p v)+ === [ a | (i, a) <- List.zip [0 ..] (elemsU v), p i a ]++prop_filterM :: Fun Int Bool -> V -> Property+prop_filterM (Fn p) v =+ fmap V.toList (NEV.filterM (\a -> logged a (p a)) v)+ === (elemsU v, List.filter p (elemsU v))++prop_ifilterM :: Fun (Int, Int) Bool -> V -> Property+prop_ifilterM (Fn2 p) v =+ fmap V.toList (NEV.ifilterM (\i a -> logged i (p i a)) v)+ === ( List.map fst ias+ , [ a | (i, a) <- ias, p i a ]+ )+ where+ ias = List.zip [0 ..] (elemsU v)++prop_takeWhile :: Fun Int Bool -> V -> Property+prop_takeWhile (Fn p) v =+ V.toList (NEV.takeWhile p v) === List.takeWhile p (elemsU v)++prop_dropWhile :: Fun Int Bool -> V -> Property+prop_dropWhile (Fn p) v =+ V.toList (NEV.dropWhile p v) === List.dropWhile p (elemsU v)++-- ---------------------------------------------------------------------- --+-- Partitioning++prop_partition :: Fun Int Bool -> V -> Property+prop_partition (Fn p) v =+ (V.toList as, V.toList bs) === List.partition p (elemsU v)+ where+ (as, bs) = NEV.partition p v++prop_partitionWith :: Fun Int (Either Int Int) -> V -> Property+prop_partitionWith (Fn f) v =+ (V.toList as, V.toList bs) === partitionEithers (List.map f (elemsU v))+ where+ (as, bs) = NEV.partitionWith f v++-- Only the contents of each side are specified, not their order.+prop_unstablePartition :: Fun Int Bool -> V -> Property+prop_unstablePartition (Fn p) v =+ (List.sort (V.toList as), List.sort (V.toList bs))+ === (List.sort ts, List.sort fs)+ where+ (as, bs) = NEV.unstablePartition p v+ (ts, fs) = List.partition p (elemsU v)++prop_span :: Fun Int Bool -> V -> Property+prop_span (Fn p) v =+ (V.toList as, V.toList bs) === List.span p (elemsU v)+ where+ (as, bs) = NEV.span p v++prop_break :: Fun Int Bool -> V -> Property+prop_break (Fn p) v =+ (V.toList as, V.toList bs) === List.break p (elemsU v)+ where+ (as, bs) = NEV.break p v++-- ---------------------------------------------------------------------- --+-- Searching++prop_elem :: Int -> V -> Property+prop_elem a v = NEV.elem (a `mod` 4) w === List.elem (a `mod` 4) (elemsU w)+ where+ w = small v++prop_notElem :: Int -> V -> Property+prop_notElem a v =+ NEV.notElem (a `mod` 4) w === List.notElem (a `mod` 4) (elemsU w)+ where+ w = small v++prop_find :: Fun Int Bool -> V -> Property+prop_find (Fn p) v = NEV.find p v === List.find p (elemsU v)++prop_findIndex :: Fun Int Bool -> V -> Property+prop_findIndex (Fn p) v = NEV.findIndex p v === List.findIndex p (elemsU v)++prop_findIndices :: Fun Int Bool -> V -> Property+prop_findIndices (Fn p) v =+ V.toList (NEV.findIndices p v) === List.findIndices p (elemsU v)++prop_elemIndex :: Int -> V -> Property+prop_elemIndex a v =+ NEV.elemIndex (a `mod` 4) w === List.elemIndex (a `mod` 4) (elemsU w)+ where+ w = small v++prop_elemIndices :: Int -> V -> Property+prop_elemIndices a v =+ V.toList (NEV.elemIndices (a `mod` 4) w)+ === List.elemIndices (a `mod` 4) (elemsU w)+ where+ w = small v
+ test/Test/Data/Vector/NonEmpty/ScansU.hs view
@@ -0,0 +1,215 @@+-- |+-- Module : Test.Data.Vector.NonEmpty.ScansU+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : experimental+-- Portability : non-portable+--+-- Properties for prefix sums (scans) and transformations.+--+-- Scan functions are arbitrary, hence neither associative nor commutative,+-- so the models pin down scan direction and argument order.+--+module Test.Data.Vector.NonEmpty.ScansU+( tests+) where+++import qualified Data.List as List+import qualified Data.Vector.Unboxed as V+import Data.Vector.NonEmpty.Unboxed (NonEmptyUVector)+import qualified Data.Vector.NonEmpty.Unboxed as NEV++import Test.Data.Vector.NonEmpty.Util+import Test.QuickCheck+import Test.Tasty+import Test.Tasty.QuickCheck+++tests :: TestTree+tests = testGroup "Scans (unboxed)"+ [ testGroup "Prefix sums"+ [ testProperty "prop_prescanl" prop_prescanl+ , testProperty "prop_prescanl'" prop_prescanl'+ , testProperty "prop_postscanl" prop_postscanl+ , testProperty "prop_postscanl'" prop_postscanl'+ , testProperty "prop_scanl" prop_scanl+ , testProperty "prop_scanl'" prop_scanl'+ , testProperty "prop_scanl1" prop_scanl1+ , testProperty "prop_scanl1'" prop_scanl1'+ , testProperty "prop_iscanl" prop_iscanl+ , testProperty "prop_iscanl'" prop_iscanl'+ , testProperty "prop_prescanr" prop_prescanr+ , testProperty "prop_prescanr'" prop_prescanr'+ , testProperty "prop_postscanr" prop_postscanr+ , testProperty "prop_postscanr'" prop_postscanr'+ , testProperty "prop_scanr" prop_scanr+ , testProperty "prop_scanr'" prop_scanr'+ , testProperty "prop_scanr1" prop_scanr1+ , testProperty "prop_scanr1'" prop_scanr1'+ , testProperty "prop_iscanr" prop_iscanr+ , testProperty "prop_iscanr'" prop_iscanr'+ ]+ , testGroup "Intersperse tests"+ [ testProperty "prop_intersperse" prop_intersperse+ , testProperty "prop_intersperse_length" prop_intersperse_length+ , testProperty "prop_intersperse_first_last" prop_intersperse_first_last+ , testProperty "prop_intersperse_separator" prop_intersperse_separator+ , testProperty "prop_intersperse_reconstruction" prop_intersperse_reconstruction+ , testProperty "prop_intersperse_singleton" prop_intersperse_singleton+ , testProperty "prop_explicit_examples" prop_explicit_examples+ ]+ ]++type V = NonEmptyUVector Int++-- ---------------------------------------------------------------------- --+-- Models++-- | Left scan over @(index, element)@ pairs.+--+iscanlList :: (Int -> a -> b -> a) -> a -> [b] -> [a]+iscanlList f z = List.scanl (\acc (i, b) -> f i acc b) z . List.zip [0 ..]++-- | Right scan over @(index, element)@ pairs.+--+iscanrList :: (Int -> a -> b -> b) -> b -> [a] -> [b]+iscanrList f z = List.scanr (\(i, a) acc -> f i a acc) z . List.zip [0 ..]++-- ---------------------------------------------------------------------- --+-- Left scans++prop_prescanl :: Fun (Int, Int) Int -> Int -> V -> Property+prop_prescanl (Fn2 f) z v =+ elemsU (NEV.prescanl f z v)+ === List.take (NEV.length v) (List.scanl f z (elemsU v))++prop_prescanl' :: Fun (Int, Int) Int -> Int -> V -> Property+prop_prescanl' (Fn2 f) z v =+ elemsU (NEV.prescanl' f z v)+ === List.take (NEV.length v) (List.scanl f z (elemsU v))++prop_postscanl :: Fun (Int, Int) Int -> Int -> V -> Property+prop_postscanl (Fn2 f) z v =+ elemsU (NEV.postscanl f z v) === List.drop 1 (List.scanl f z (elemsU v))++prop_postscanl' :: Fun (Int, Int) Int -> Int -> V -> Property+prop_postscanl' (Fn2 f) z v =+ elemsU (NEV.postscanl' f z v) === List.drop 1 (List.scanl f z (elemsU v))++prop_scanl :: Fun (Int, Int) Int -> Int -> V -> Property+prop_scanl (Fn2 f) z v = elemsU (NEV.scanl f z v) === List.scanl f z (elemsU v)++prop_scanl' :: Fun (Int, Int) Int -> Int -> V -> Property+prop_scanl' (Fn2 f) z v = elemsU (NEV.scanl' f z v) === List.scanl f z (elemsU v)++prop_scanl1 :: Fun (Int, Int) Int -> V -> Property+prop_scanl1 (Fn2 f) v = elemsU (NEV.scanl1 f v) === List.scanl1 f (elemsU v)++prop_scanl1' :: Fun (Int, Int) Int -> V -> Property+prop_scanl1' (Fn2 f) v = elemsU (NEV.scanl1' f v) === List.scanl1 f (elemsU v)++prop_iscanl :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_iscanl (Fn3 f) z v =+ elemsU (NEV.iscanl f z v) === iscanlList f z (elemsU v)++prop_iscanl' :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_iscanl' (Fn3 f) z v =+ elemsU (NEV.iscanl' f z v) === iscanlList f z (elemsU v)++-- ---------------------------------------------------------------------- --+-- Right scans++prop_prescanr :: Fun (Int, Int) Int -> Int -> V -> Property+prop_prescanr (Fn2 f) z v =+ elemsU (NEV.prescanr f z v) === List.drop 1 (List.scanr f z (elemsU v))++prop_prescanr' :: Fun (Int, Int) Int -> Int -> V -> Property+prop_prescanr' (Fn2 f) z v =+ elemsU (NEV.prescanr' f z v) === List.drop 1 (List.scanr f z (elemsU v))++prop_postscanr :: Fun (Int, Int) Int -> Int -> V -> Property+prop_postscanr (Fn2 f) z v =+ elemsU (NEV.postscanr f z v)+ === List.take (NEV.length v) (List.scanr f z (elemsU v))++prop_postscanr' :: Fun (Int, Int) Int -> Int -> V -> Property+prop_postscanr' (Fn2 f) z v =+ elemsU (NEV.postscanr' f z v)+ === List.take (NEV.length v) (List.scanr f z (elemsU v))++prop_scanr :: Fun (Int, Int) Int -> Int -> V -> Property+prop_scanr (Fn2 f) z v = elemsU (NEV.scanr f z v) === List.scanr f z (elemsU v)++prop_scanr' :: Fun (Int, Int) Int -> Int -> V -> Property+prop_scanr' (Fn2 f) z v = elemsU (NEV.scanr' f z v) === List.scanr f z (elemsU v)++prop_scanr1 :: Fun (Int, Int) Int -> V -> Property+prop_scanr1 (Fn2 f) v = elemsU (NEV.scanr1 f v) === List.scanr1 f (elemsU v)++prop_scanr1' :: Fun (Int, Int) Int -> V -> Property+prop_scanr1' (Fn2 f) v = elemsU (NEV.scanr1' f v) === List.scanr1 f (elemsU v)++prop_iscanr :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_iscanr (Fn3 f) z v =+ elemsU (NEV.iscanr f z v) === iscanrList f z (elemsU v)++prop_iscanr' :: Fun (Int, Int, Int) Int -> Int -> V -> Property+prop_iscanr' (Fn3 f) z v =+ elemsU (NEV.iscanr' f z v) === iscanrList f z (elemsU v)++-- ---------------------------------------------------------------------- --+-- Intersperse properties++prop_intersperse :: Int -> V -> Property+prop_intersperse sep v =+ elemsU (NEV.intersperse sep v) === List.intersperse sep (elemsU v)++-- For vectors with length > 1, interspersing should result in length 2*n - 1+prop_intersperse_length :: Int -> V -> Bool+prop_intersperse_length sep v =+ let result = NEV.intersperse sep v+ originalLen = NEV.length v+ in if originalLen > 1+ then NEV.length result == 2 * originalLen - 1+ else NEV.length result == originalLen++-- The first and last elements of the result should match the original vector+prop_intersperse_first_last :: Int -> V -> Bool+prop_intersperse_first_last sep v =+ let result = NEV.intersperse sep v+ in NEV.head result == NEV.head v && NEV.last result == NEV.last v++-- Every odd-indexed element should be the separator (for vectors with length > 1)+prop_intersperse_separator :: Int -> V -> Bool+prop_intersperse_separator sep v =+ let result = NEV.intersperse sep v+ in NEV.length v <= 1 ||+ all (\i -> result NEV.! (2*i+1) == sep) [0 .. NEV.length v - 2]++-- If we remove the separator, we should get back the original vector+prop_intersperse_reconstruction :: Int -> V -> Bool+prop_intersperse_reconstruction sep v =+ let result = NEV.intersperse sep v+ resultVector = NEV.toVector result+ reconstructed = V.ifilter (\i _ -> i `mod` 2 == 0) resultVector+ in V.toList reconstructed == NEV.toList v++-- For singleton vectors, interspersing should not change the vector+prop_intersperse_singleton :: Int -> Int -> Bool+prop_intersperse_singleton x sep =+ let singleton = NEV.singleton x+ result = NEV.intersperse sep singleton+ in result == singleton++-- Explicit test cases for edge cases and examples combined into one property+prop_explicit_examples :: Property+prop_explicit_examples =+ let normalCase = NEV.intersperse (0 :: Int) (NEV.unsafeFromList [1,2,3 :: Int])+ === NEV.unsafeFromList [1,0,2,0,3 :: Int]++ singletonCase = NEV.intersperse (0 :: Int) (NEV.singleton (5 :: Int))+ === NEV.singleton (5 :: Int)+ in normalCase .&&. singletonCase
test/Test/Data/Vector/NonEmpty/Util.hs view
@@ -2,7 +2,7 @@ {-# OPTIONS_GHC -Wno-orphans #-} -- | -- Module : Test.Data.Vector.NonEmpty.Util--- Copyright : (c) 2019-2026 Emily Pillmore+-- Copyright : (c) 2019-2026 Emily Pillmore, Koz Ross -- License : BSD-style -- -- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>@@ -19,15 +19,23 @@ module Test.Data.Vector.NonEmpty.Util ( -- * Building and observing vectors vec+, vecU , elems+, elemsU , elems1+, elems1U , whenNonEmpty -- * Generators , genIndex+, genIndexU , genIndices+, genIndicesU , genOutOfBounds+, genOutOfBoundsU , genSlice+, genSliceU , genUpdates+, genUpdatesU -- * Effects , logged , unfoldStep@@ -49,7 +57,9 @@ import Data.List.NonEmpty (NonEmpty(..)) import Data.Maybe (fromMaybe, listToMaybe) import qualified Data.Vector as V+import qualified Data.Vector.Unboxed as VU import Data.Vector.NonEmpty.Internal (NonEmptyVector(..))+import Data.Vector.NonEmpty.Unboxed.Internal (NonEmptyUVector(..)) import Test.QuickCheck @@ -58,6 +68,10 @@ arbitrary = vec . getNonEmpty <$> arbitrary shrink = fmap (vec . getNonEmpty) . shrink . NonEmpty . elems +instance (Arbitrary a, VU.Unbox a) => Arbitrary (NonEmptyUVector a) where+ arbitrary = vecU . getNonEmpty <$> arbitrary+ shrink = fmap (vecU . getNonEmpty) . shrink . NonEmpty . elemsU+ -- ---------------------------------------------------------------------- -- -- Building and observing vectors @@ -67,17 +81,32 @@ vec :: [a] -> NonEmptyVector a vec = NonEmptyVector . V.fromList +-- | As 'vec', but for unboxed representations.+--+vecU :: VU.Unbox a => [a] -> NonEmptyUVector a+vecU = NonEmptyUVector . VU.fromList+ -- | The elements of a non-empty vector, read from its representation. -- elems :: NonEmptyVector a -> [a] elems = V.toList . _neVec +-- | As 'elems', but for unboxed representations.+--+elemsU :: VU.Unbox a => NonEmptyUVector a -> [a]+elemsU = VU.toList . _neUvec+ -- | The elements of a non-empty vector as a non-empty list, read from its -- representation. -- elems1 :: NonEmptyVector a -> NonEmpty a elems1 (NonEmptyVector v) = V.unsafeHead v :| V.toList (V.unsafeTail v) +-- | As 'elems1', but for unboxed representations.+--+elems1U :: VU.Unbox a => NonEmptyUVector a -> NonEmpty a+elems1U (NonEmptyUVector v) = VU.unsafeHead v :| VU.toList (VU.unsafeTail v)+ -- | Model of the 'Maybe'-valued constructors: 'Nothing' exactly when the -- result would be empty. --@@ -93,11 +122,21 @@ genIndex :: NonEmptyVector a -> Gen Int genIndex (NonEmptyVector v) = choose (0, V.length v - 1) +-- | As 'genIndex', but for unboxed representations.+--+genIndexU :: VU.Unbox a => NonEmptyUVector a -> Gen Int+genIndexU (NonEmptyUVector v) = choose (0, VU.length v - 1)+ -- | A non-empty vector of valid indices into the vector. -- genIndices :: NonEmptyVector a -> Gen (NonEmptyVector Int) genIndices v = vec <$> listOf1 (genIndex v) +-- | As 'genIndices', but for unboxed representations.+--+genIndicesU :: VU.Unbox a => NonEmptyUVector a -> Gen (NonEmptyUVector Int)+genIndicesU v = vecU <$> listOf1 (genIndexU v)+ -- | An index outside the bounds of the vector, on either side. -- genOutOfBounds :: NonEmptyVector a -> Gen Int@@ -108,6 +147,16 @@ where n = V.length v +-- | As 'genOutOfBounds', but for unboxed representations.+--+genOutOfBoundsU :: VU.Unbox a => NonEmptyUVector a -> Gen Int+genOutOfBoundsU (NonEmptyUVector v) = oneof+ [ choose (-10, -1)+ , choose (n, n + 10)+ ]+ where+ n = VU.length v+ -- | A valid @(offset, length)@ slice of the vector, possibly empty. -- genSlice :: NonEmptyVector a -> Gen (Int, Int)@@ -118,10 +167,24 @@ where n = V.length v +-- | As 'genSlice', but for unboxed representations.+genSliceU :: VU.Unbox a => NonEmptyUVector a -> Gen (Int, Int)+genSliceU (NonEmptyUVector v) = do+ i <- choose (0, n)+ m <- choose (0, n - i)+ pure (i, m)+ where+ n = VU.length v+ -- | A list of updates at valid indices of the vector. -- genUpdates :: Arbitrary b => NonEmptyVector a -> Gen [(Int, b)] genUpdates v = listOf ((,) <$> genIndex v <*> arbitrary)++-- | As 'genUpdates', but for unboxed representations.+--+genUpdatesU :: (VU.Unbox a, Arbitrary b) => NonEmptyUVector a -> Gen [(Int, b)]+genUpdatesU v = listOf ((,) <$> genIndexU v <*> arbitrary) -- ---------------------------------------------------------------------- -- -- Effects