diff --git a/semigroups.cabal b/semigroups.cabal
--- a/semigroups.cabal
+++ b/semigroups.cabal
@@ -1,6 +1,6 @@
 name:          semigroups
 category:      Algebra, Data, Data Structures, Math
-version:       0.9.2
+version:       0.10
 license:       BSD3
 cabal-version: >= 1.10
 license-file:  LICENSE
@@ -36,11 +36,16 @@
 
   if flag(base2)
     build-depends: base == 2.*
+    cpp-options: -DBASE2
   else
     build-depends:
-      base       >= 3 && < 5,
-      containers >= 0.3 && < 0.6,
-      nats       >= 0.1
+      base                 >= 3    && < 5,
+      bytestring           >= 0.9  && < 0.11,
+      containers           >= 0.3  && < 0.6,
+      hashable             >= 1.1  && < 1.3,
+      nats                 >= 0.1  && < 1,
+      text                 >= 0.10 && < 0.12,
+      unordered-containers >= 0.2  && < 0.3
 
   hs-source-dirs: src
   ghc-options:    -Wall
diff --git a/src/Data/List/NonEmpty.hs b/src/Data/List/NonEmpty.hs
--- a/src/Data/List/NonEmpty.hs
+++ b/src/Data/List/NonEmpty.hs
@@ -27,8 +27,9 @@
    , scanr       -- :: Foldable f => (a -> b -> b) -> b -> f a -> NonEmpty b
    , scanl1      -- :: (a -> a -> a) -> NonEmpty a -> NonEmpty a
    , scanr1      -- :: (a -> a -> a) -> NonEmpty a -> NonEmpty a
-   --, transpose   -- :: NonEmpty (NonEmpty a) -> NonEmpty (NonEmpty a)
+   -- , transpose   -- :: NonEmpty (NonEmpty a) -> NonEmpty (NonEmpty a)
    -- * Basic functions
+   , length      -- :: NonEmpty a -> Int
    , head        -- :: NonEmpty a -> a
    , tail        -- :: NonEmpty a -> [a]
    , last        -- :: NonEmpty a -> a
@@ -61,6 +62,9 @@
    , groupBy1    -- :: (a -> a -> Bool) -> NonEmpty a -> NonEmpty (NonEmpty a)
    -- * Sublist predicates
    , isPrefixOf  -- :: Foldable f => f a -> NonEmpty a -> Bool
+   -- * \"Set\" operations
+   , nub         -- :: Eq a => NonEmpty a -> NonEmpty a
+   , nubBy       -- :: (a -> a -> Bool) -> NonEmpty a -> NonEmpty a
    -- * Indexing streams
    , (!!)        -- :: NonEmpty a -> Int -> a
    -- * Zipping and unzipping streams
@@ -80,6 +84,7 @@
    ) where
 
 
+import qualified Prelude
 import Prelude hiding
   ( head, tail, map, reverse
   , scanl, scanl1, scanr, scanr1
@@ -88,8 +93,10 @@
   , (!!), zip, unzip, zipWith, words
   , unwords, lines, unlines, break, span
   , splitAt, foldr, foldl, last, init
+  , length
   )
 
+
 import Control.Applicative
 -- import Control.Comonad
 import Control.Monad
@@ -116,6 +123,10 @@
 #endif
   )
 
+length :: NonEmpty a -> Int
+length (_ :| xs) = 1 + Prelude.length xs
+{-# INLINE length #-}
+
 xor :: NonEmpty Bool -> Bool
 xor (x :| xs)   = foldr xor' x xs
   where xor' True y  = not y
@@ -504,3 +515,18 @@
 unlines :: NonEmpty String -> NonEmpty Char
 unlines = lift List.unlines
 {-# INLINE unlines #-}
+
+-- | The 'nub' function removes duplicate elements from a list. In
+-- particular, it keeps only the first occurence of each element.
+-- (The name 'nub' means \'essence\'.)
+-- It is a special case of 'nubBy', which allows the programmer to
+-- supply their own inequality test.
+nub :: Eq a => NonEmpty a -> NonEmpty a
+nub = nubBy (==)
+
+-- | The 'nubBy' function behaves just like 'nub', except it uses a
+-- user-supplied equality predicate instead of the overloaded '=='
+-- function.
+nubBy :: (a -> a -> Bool) -> NonEmpty a -> NonEmpty a
+nubBy eq (a :| as) = a :| List.nubBy eq (List.filter (\b -> not (eq a b)) as)
+
diff --git a/src/Data/Semigroup.hs b/src/Data/Semigroup.hs
--- a/src/Data/Semigroup.hs
+++ b/src/Data/Semigroup.hs
@@ -4,6 +4,7 @@
 #endif
 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
 {-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE Trustworthy #-}
 #endif
 -----------------------------------------------------------------------------
 -- |
@@ -72,6 +73,15 @@
 import Data.Map (Map)
 import Data.IntMap (IntMap)
 
+#ifndef BASE2
+import Data.ByteString as Strict
+import Data.ByteString.Lazy as Lazy
+import Data.Text as Strict
+import Data.Text.Lazy as Lazy
+import Data.Hashable
+import Data.HashMap.Lazy as Lazy
+#endif
+
 #ifdef LANGUAGE_DeriveDataTypeable
 import Data.Data
 #endif
@@ -239,7 +249,7 @@
   mempty = minBound
   mappend = (<>)
 
--- | Use @'Option' ('First' a)@ -- to get the behavior of 'Data.Monoid.First'
+-- | Use @'Option' ('First' a)@ to get the behavior of 'Data.Monoid.First' from @Data.Monoid@.
 newtype First a = First { getFirst :: a } deriving
   ( Eq, Ord, Bounded, Show, Read
 #ifdef LANGUAGE_DeriveDataTypeable
@@ -252,7 +262,7 @@
   a <> _ = a
   times1p _ a = a
 
--- | Use @'Option' ('Last' a)@ -- to get the behavior of 'Data.Monoid.Last'
+-- | Use @'Option' ('Last' a)@ to get the behavior of 'Data.Monoid.Last' from @Data.Monoid@
 newtype Last a = Last { getLast :: a } deriving
   ( Eq, Ord, Bounded, Show, Read
 #ifdef LANGUAGE_DeriveDataTypeable
@@ -266,7 +276,23 @@
 
 -- (==)/XNOR on Bool forms a 'Semigroup', but has no good name
 
+#ifndef BASE2
+instance Semigroup Strict.ByteString where
+  (<>) = mappend
 
+instance Semigroup Lazy.ByteString where
+  (<>) = mappend
+
+instance Semigroup Strict.Text where
+  (<>) = mappend
+
+instance Semigroup Lazy.Text where
+  (<>) = mappend
+
+instance (Hashable k, Eq k) => Semigroup (Lazy.HashMap k a) where
+  (<>) = mappend
+#endif
+
 -- | Provide a Semigroup for an arbitrary Monoid.
 newtype WrappedMonoid m = WrapMonoid
   { unwrapMonoid :: m } deriving
@@ -326,7 +352,7 @@
   a <|> _ = a
 
 instance MonadPlus Option where
-  mzero = empty
+  mzero = Option Nothing
   mplus = (<|>)
 
 instance MonadFix Option where
@@ -340,6 +366,7 @@
   traverse f (Option (Just a)) = Option . Just <$> f a
   traverse _ (Option Nothing)  = pure (Option Nothing)
 
+-- | Fold an 'Option' case-wise, just like 'maybe'.
 option :: b -> (a -> b) -> Option a -> b
 option n j (Option m) = maybe n j m
 
@@ -347,7 +374,7 @@
   Option a <> Option b = Option (a <> b)
 
 instance Semigroup a => Monoid (Option a) where
-  mempty = empty
+  mempty = Option Nothing
   Option a `mappend` Option b = Option (a <> b)
 
 -- | This lets you use a difference list of a Semigroup as a Monoid.
