diff --git a/hw-prim.cabal b/hw-prim.cabal
--- a/hw-prim.cabal
+++ b/hw-prim.cabal
@@ -1,7 +1,7 @@
 cabal-version:  2.2
 
 name:           hw-prim
-version:        0.6.2.24
+version:        0.6.2.25
 synopsis:       Primitive functions and data types
 description:    Primitive functions and data types.
 category:       Data
@@ -29,14 +29,14 @@
 
 common base                 { build-depends: base                 >= 4          && < 5      }
 
-common QuickCheck           { build-depends: QuickCheck           >= 2.10       && < 2.12   }
+common QuickCheck           { build-depends: QuickCheck           >= 2.10       && < 2.14   }
 common bytestring           { build-depends: bytestring           >= 0.9        && < 0.11   }
 common criterion            { build-depends: criterion            >= 1.2        && < 1.6    }
 common directory            { build-depends: directory            >= 1.2        && < 1.4    }
 common exceptions           { build-depends: exceptions           >= 0.8        && < 0.11   }
 common ghc-prim             { build-depends: ghc-prim                                       }
 common hedgehog             { build-depends: hedgehog             >= 0.5        && < 1.1    }
-common hspec                { build-depends: hspec                >= 2.4        && < 2.6    }
+common hspec                { build-depends: hspec                >= 2.4        && < 2.8    }
 common hw-hspec-hedgehog    { build-depends: hw-hspec-hedgehog    >= 0.1        && < 0.2    }
 common mmap                 { build-depends: mmap                 >= 0.5        && < 0.6    }
 common semigroups           { build-depends: semigroups           >= 0.8.4      && < 0.20   }
@@ -67,6 +67,7 @@
     HaskellWorks.Data.Char
     HaskellWorks.Data.Char.IsChar
     HaskellWorks.Data.Concat
+    HaskellWorks.Data.Cons
     HaskellWorks.Data.Container
     HaskellWorks.Data.Decode
     HaskellWorks.Data.Drop
@@ -78,6 +79,8 @@
     HaskellWorks.Data.Head
     HaskellWorks.Data.Length
     HaskellWorks.Data.Naive
+    HaskellWorks.Data.Null
+    HaskellWorks.Data.Ops
     HaskellWorks.Data.Positioning
     HaskellWorks.Data.Product
     HaskellWorks.Data.Search
@@ -87,6 +90,7 @@
     HaskellWorks.Data.TreeCursor
     HaskellWorks.Data.Uncons
     HaskellWorks.Data.Unsign
+    HaskellWorks.Data.Unsnoc
     HaskellWorks.Data.Vector.AsVector64
     HaskellWorks.Data.Vector.AsVector64ns
     HaskellWorks.Data.Vector.AsVector64s
diff --git a/src/HaskellWorks/Data/Cons.hs b/src/HaskellWorks/Data/Cons.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Cons.hs
@@ -0,0 +1,94 @@
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+module HaskellWorks.Data.Cons
+    ( Cons(..)
+    ) where
+
+import Data.Int
+import Data.Word
+import HaskellWorks.Data.Container
+
+import qualified Data.ByteString      as BS
+import qualified Data.Vector          as DV
+import qualified Data.Vector.Storable as DVS
+
+class Container v => Cons v where
+  cons :: Elem v -> v -> v
+
+instance Cons [a] where
+  cons = (:)
+  {-# INLINE cons #-}
+
+instance Cons BS.ByteString where
+  cons = BS.cons
+  {-# INLINE cons #-}
+
+instance Cons (DV.Vector Word8) where
+  cons = DV.cons
+  {-# INLINE cons #-}
+
+instance Cons (DV.Vector Word16) where
+  cons = DV.cons
+  {-# INLINE cons #-}
+
+instance Cons (DV.Vector Word32) where
+  cons = DV.cons
+  {-# INLINE cons #-}
+
+instance Cons (DV.Vector Word64) where
+  cons = DV.cons
+  {-# INLINE cons #-}
+
+instance Cons (DVS.Vector Word8) where
+  cons = DVS.cons
+  {-# INLINE cons #-}
+
+instance Cons (DVS.Vector Word16) where
+  cons = DVS.cons
+  {-# INLINE cons #-}
+
+instance Cons (DVS.Vector Word32) where
+  cons = DVS.cons
+  {-# INLINE cons #-}
+
+instance Cons (DVS.Vector Word64) where
+  cons = DVS.cons
+  {-# INLINE cons #-}
+
+instance Cons (DV.Vector Int8) where
+  cons = DV.cons
+  {-# INLINE cons #-}
+
+instance Cons (DV.Vector Int16) where
+  cons = DV.cons
+  {-# INLINE cons #-}
+
+instance Cons (DV.Vector Int32) where
+  cons = DV.cons
+  {-# INLINE cons #-}
+
+instance Cons (DV.Vector Int64) where
+  cons = DV.cons
+  {-# INLINE cons #-}
+
+instance Cons (DVS.Vector Int8) where
+  cons = DVS.cons
+  {-# INLINE cons #-}
+
+instance Cons (DVS.Vector Int16) where
+  cons = DVS.cons
+  {-# INLINE cons #-}
+
+instance Cons (DVS.Vector Int32) where
+  cons = DVS.cons
+  {-# INLINE cons #-}
+
+instance Cons (DVS.Vector Int64) where
+  cons = DVS.cons
+  {-# INLINE cons #-}
+
+instance Cons (DVS.Vector Int) where
+  cons = DVS.cons
+  {-# INLINE cons #-}
diff --git a/src/HaskellWorks/Data/Null.hs b/src/HaskellWorks/Data/Null.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Null.hs
@@ -0,0 +1,96 @@
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+module HaskellWorks.Data.Null
+    ( Null(..)
+    ) where
+
+import Data.Int
+import Data.Word
+import HaskellWorks.Data.Container
+
+import qualified Data.ByteString      as BS
+import qualified Data.List            as L
+import qualified Data.Vector          as DV
+import qualified Data.Vector.Storable as DVS
+
+class Container a => Null a where
+  null :: a -> Bool
+
+instance Null [a] where
+  null = L.null
+  {-# INLINE null #-}
+
+instance Null BS.ByteString where
+  null = BS.null
+  {-# INLINE null #-}
+
+instance Null (DV.Vector Word8) where
+  null = DV.null
+  {-# INLINE null #-}
+
+instance Null (DV.Vector Word16) where
+  null = DV.null
+  {-# INLINE null #-}
+
+instance Null (DV.Vector Word32) where
+  null = DV.null
+  {-# INLINE null #-}
+
+instance Null (DV.Vector Word64) where
+  null = DV.null
+  {-# INLINE null #-}
+
+instance Null (DVS.Vector Word8) where
+  null = DVS.null
+  {-# INLINE null #-}
+
+instance Null (DVS.Vector Word16) where
+  null = DVS.null
+  {-# INLINE null #-}
+
+instance Null (DVS.Vector Word32) where
+  null = DVS.null
+  {-# INLINE null #-}
+
+instance Null (DVS.Vector Word64) where
+  null = DVS.null
+  {-# INLINE null #-}
+
+instance Null (DV.Vector Int8) where
+  null = DV.null
+  {-# INLINE null #-}
+
+instance Null (DV.Vector Int16) where
+  null = DV.null
+  {-# INLINE null #-}
+
+instance Null (DV.Vector Int32) where
+  null = DV.null
+  {-# INLINE null #-}
+
+instance Null (DV.Vector Int64) where
+  null = DV.null
+  {-# INLINE null #-}
+
+instance Null (DVS.Vector Int8) where
+  null = DVS.null
+  {-# INLINE null #-}
+
+instance Null (DVS.Vector Int16) where
+  null = DVS.null
+  {-# INLINE null #-}
+
+instance Null (DVS.Vector Int32) where
+  null = DVS.null
+  {-# INLINE null #-}
+
+instance Null (DVS.Vector Int64) where
+  null = DVS.null
+  {-# INLINE null #-}
+
+instance Null (DVS.Vector Int) where
+  null = DVS.null
+  {-# INLINE null #-}
diff --git a/src/HaskellWorks/Data/Ops.hs b/src/HaskellWorks/Data/Ops.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Ops.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE Rank2Types      #-}
+
+module HaskellWorks.Data.Ops
+  ( (<|)
+  , (|>)
+  , (><)
+  ) where
+
+import Data.Semigroup (Semigroup, (<>))
+
+import qualified HaskellWorks.Data.Cons      as HW
+import qualified HaskellWorks.Data.Container as HW
+import qualified HaskellWorks.Data.Snoc      as HW
+
+infixr 5 <|, ><
+
+infixl 5 |>
+
+(<|) :: HW.Cons v => HW.Elem v -> v -> v
+(<|) = HW.cons
+{-# INLINE (<|) #-}
+
+(|>) :: HW.Snoc v => v -> HW.Elem v -> v
+(|>) = HW.snoc
+{-# INLINE (|>) #-}
+
+(><) :: (Semigroup v, HW.Container v) => v -> v -> v
+(><) = (<>)
+{-# INLINE (><) #-}
diff --git a/src/HaskellWorks/Data/Unsnoc.hs b/src/HaskellWorks/Data/Unsnoc.hs
new file mode 100644
--- /dev/null
+++ b/src/HaskellWorks/Data/Unsnoc.hs
@@ -0,0 +1,99 @@
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+module HaskellWorks.Data.Unsnoc
+    ( Container(..)
+    , Unsnoc(..)
+    ) where
+
+import Data.Int
+import Data.Maybe
+import Data.Word
+import HaskellWorks.Data.Container
+import Prelude                     hiding (drop)
+
+import qualified Data.ByteString      as BS
+import qualified Data.Vector          as DV
+import qualified Data.Vector.Storable as DVS
+
+class Unsnoc v where
+  unsnoc :: v -> Maybe (Elem v, v)
+
+instance Unsnoc String where
+  unsnoc s = case reverse s of
+    (x:xs) -> Just (x, reverse xs)
+    _      -> Nothing
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc BS.ByteString where
+  unsnoc s = if BS.length s == 0 then Nothing else Just (BS.last s, BS.take (BS.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DV.Vector Word8) where
+  unsnoc s = if DV.length s == 0 then Nothing else Just (DV.last s, DV.take (DV.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DV.Vector Word16) where
+  unsnoc s = if DV.length s == 0 then Nothing else Just (DV.last s, DV.take (DV.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DV.Vector Word32) where
+  unsnoc s = if DV.length s == 0 then Nothing else Just (DV.last s, DV.take (DV.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DV.Vector Word64) where
+  unsnoc s = if DV.length s == 0 then Nothing else Just (DV.last s, DV.take (DV.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DVS.Vector Word8) where
+  unsnoc s = if DVS.length s == 0 then Nothing else Just (DVS.last s, DVS.take (DVS.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DVS.Vector Word16) where
+  unsnoc s = if DVS.length s == 0 then Nothing else Just (DVS.last s, DVS.take (DVS.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DVS.Vector Word32) where
+  unsnoc s = if DVS.length s == 0 then Nothing else Just (DVS.last s, DVS.take (DVS.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DVS.Vector Word64) where
+  unsnoc s = if DVS.length s == 0 then Nothing else Just (DVS.last s, DVS.take (DVS.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DV.Vector Int8) where
+  unsnoc s = if DV.length s == 0 then Nothing else Just (DV.last s, DV.take (DV.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DV.Vector Int16) where
+  unsnoc s = if DV.length s == 0 then Nothing else Just (DV.last s, DV.take (DV.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DV.Vector Int32) where
+  unsnoc s = if DV.length s == 0 then Nothing else Just (DV.last s, DV.take (DV.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DV.Vector Int64) where
+  unsnoc s = if DV.length s == 0 then Nothing else Just (DV.last s, DV.take (DV.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DVS.Vector Int8) where
+  unsnoc s = if DVS.length s == 0 then Nothing else Just (DVS.last s, DVS.take (DVS.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DVS.Vector Int16) where
+  unsnoc s = if DVS.length s == 0 then Nothing else Just (DVS.last s, DVS.take (DVS.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DVS.Vector Int32) where
+  unsnoc s = if DVS.length s == 0 then Nothing else Just (DVS.last s, DVS.take (DVS.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DVS.Vector Int64) where
+  unsnoc s = if DVS.length s == 0 then Nothing else Just (DVS.last s, DVS.take (DVS.length s - 1) s)
+  {-# INLINE unsnoc   #-}
+
+instance Unsnoc (DVS.Vector Int) where
+  unsnoc s = if DVS.length s == 0 then Nothing else Just (DVS.last s, DVS.take (DVS.length s - 1) s)
+  {-# INLINE unsnoc   #-}
