diff --git a/src/Data/Witherable.hs b/src/Data/Witherable.hs
--- a/src/Data/Witherable.hs
+++ b/src/Data/Witherable.hs
@@ -17,8 +17,6 @@
 module Data.Witherable
   ( Filterable(..)
   , Witherable(..)
-  , witherM
-  , blightM
   , ordNub
   , hashNub
   , forMaybe
@@ -43,13 +41,16 @@
 import qualified Data.Map.Lazy as M
 import qualified Data.Sequence as S
 import qualified Data.Vector as V
-import qualified Data.HashMap.Strict as HM
+import qualified Data.HashMap.Lazy as HM
 import qualified Data.Set as Set
 import qualified Data.HashSet as HSet
 import Control.Applicative
 import qualified Data.Traversable as T
 import qualified Data.Foldable as F
 import Data.Functor.Compose
+import Data.Functor.Product as P
+import Data.Functor.Sum as Sum
+import Control.Monad.Trans.Identity
 import Data.Hashable
 import Data.Functor.Identity
 import Control.Monad.Trans.Maybe
@@ -59,6 +60,9 @@
 #if (MIN_VERSION_base(4,7,0))
 import Data.Proxy
 #endif
+#if __GLASGOW_HASKELL__ >= 708
+import Data.Coerce (coerce)
+#endif
 import Prelude -- Fix redundant import warning
 
 -- | This type allows combinators to take a 'Filter' specializing the parameter @f@.
@@ -87,6 +91,10 @@
   {-# INLINE pure #-}
   Peat f <*> Peat g = Peat $ \h -> f h <*> g h
   {-# INLINE (<*>) #-}
+#if MIN_VERSION_base(4,10,0)
+  liftA2 f (Peat xs) (Peat ys) = Peat $ \h -> liftA2 f (xs h) (ys h)
+  {-# INLINE liftA2 #-}
+#endif
 
 -- | Reconstitute a 'Filter' from its monomorphic form.
 cloneFilter :: FilterLike (Peat a b) s t a b -> Filter s t a b
@@ -103,9 +111,19 @@
 forMaybeOf = flip
 {-# INLINE forMaybeOf #-}
 
+-- In case mapMaybeOf or filterOf is called with a function of
+-- unknown arity, we don't want to slow things down to raise
+-- its arity.
+idDot :: (a -> b) -> a -> Identity b
+#if __GLASGOW_HASKELL__ >= 708
+idDot = coerce
+#else
+idDot = (Identity .)
+#endif
+
 -- | 'mapMaybe' through a filter.
 mapMaybeOf :: FilterLike Identity s t a b -> (a -> Maybe b) -> s -> t
-mapMaybeOf w f = runIdentity . w (Identity . f)
+mapMaybeOf w f = runIdentity . w (idDot f)
 {-# INLINE mapMaybeOf #-}
 
 -- | 'catMaybes' through a filter.
@@ -120,7 +138,7 @@
 
 -- | Filter each element of a structure targeted by a 'Filter'.
 filterOf :: FilterLike' Identity s a -> (a -> Bool) -> s -> s
-filterOf w f = runIdentity . filterAOf w (Identity . f)
+filterOf w f = runIdentity . filterAOf w (idDot f)
 {-# INLINE filterOf #-}
 
 -- | Like 'Functor', but it include 'Maybe' effects.
@@ -132,6 +150,9 @@
 -- [/identity/]
 --   @'mapMaybe' Just ≡ id@
 --
+-- [/conservation/]
+--   @'mapMaybe' (Just . f) ≡ 'fmap' f@
+--
 -- [/composition/]
 --   @'mapMaybe' f . 'mapMaybe' g ≡ 'mapMaybe' (f <=< g)@
 class Functor f => Filterable f where
@@ -161,6 +182,9 @@
 -- [/identity/]
 --   @'wither' ('pure' . Just) ≡ 'pure'@
 --
+-- [/conservation/]
+--   @'wither' ('fmap' 'Just' . f) ≡ 'traverse' f@
+--
 -- [/composition/]
 --   @'Compose' . 'fmap' ('wither' f) . 'wither' g ≡ 'wither' ('Compose' . 'fmap' ('wither' f) . g)@
 --
@@ -176,6 +200,17 @@
   wither f = fmap catMaybes . T.traverse f
   {-# INLINE wither #-}
 
+  -- | @Monadic variant of 'wither'. This may have more efficient implementation.@
+  witherM :: Monad m => (a -> m (Maybe b)) -> t a -> m (t b)
+#if MIN_VERSION_base(4,8,0)
+  witherM = wither
+#elif __GLASGOW_HASKELL__ >= 708
+  witherM f = unwrapMonad . wither (coerce f)
+#else
+  witherM f = unwrapMonad . wither (WrapMonad . f)
+#endif
+  {-# INLINE witherM #-}
+
   -- | @'Compose' . 'fmap' ('filterA' f) . 'filterA' g ≡ 'filterA' (\x -> 'Compose' $ 'fmap' (\b -> (b&&) <$> f x) (g x)@
   filterA :: Applicative f => (a -> f Bool) -> t a -> f (t a)
   filterA = filterAOf wither
@@ -189,16 +224,6 @@
 forMaybe = flip wither
 {-# INLINE forMaybe #-}
 
--- | A variant of `wither` that works on 'MaybeT'.
-witherM :: (Witherable t, Monad m) => (a -> MaybeT m b) -> t a -> m (t b)
-witherM f = unwrapMonad . wither (WrapMonad . runMaybeT . f)
-{-# INLINE witherM #-}
-
--- | 'blightM' is 'witherM' with its arguments flipped.
-blightM :: (Monad m, Witherable t) => t a -> (a -> MaybeT m b) -> m (t b)
-blightM = flip witherM
-{-# INLINE blightM #-}
-
 -- | Remove the duplicate elements through a filter.
 ordNubOf :: Ord a => FilterLike' (State (Set.Set a)) s a -> s -> s
 ordNubOf w t = evalState (w f t) Set.empty
@@ -222,14 +247,14 @@
 --   occurrence. This is asymptotically faster than using
 --   'Data.List.nub' from "Data.List".
 ordNub :: (Witherable t, Ord a) => t a -> t a
-ordNub = ordNubOf wither
+ordNub = ordNubOf witherM
 {-# INLINE ordNub #-}
 
 -- | Removes duplicate elements from a list, keeping only the first
 --   occurrence. This is usually faster than 'ordNub', especially for
---   things that have a slow comparion (like 'String').
+--   things that have a slow comparison (like 'String').
 hashNub :: (Witherable t, Eq a, Hashable a) => t a -> t a
-hashNub = hashNubOf wither
+hashNub = hashNubOf witherM
 {-# INLINE hashNub #-}
 
 instance Filterable Maybe where
@@ -258,7 +283,7 @@
 
 instance Witherable [] where
   wither f = go where
-    go (x:xs) = maybe id (:) <$> f x <*> go xs
+    go (x:xs) = liftA2 (maybe id (:)) (f x) (go xs)
     go [] = pure []
   {-# INLINE[0] wither #-}
 
@@ -273,6 +298,9 @@
   filter = M.filter
 
 instance Witherable (M.Map k) where
+#if MIN_VERSION_containers(0,5,8)
+  wither f = M.traverseMaybeWithKey (const f)
+#endif
 
 instance (Eq k, Hashable k) => Filterable (HM.HashMap k) where
   mapMaybe = HM.mapMaybe
@@ -297,8 +325,7 @@
   {-# INLINABLE wither #-}
 
 instance Filterable V.Vector where
-  mapMaybe f = V.fromList . mapMaybe f . V.toList
-  {-# INLINABLE mapMaybe #-}
+  mapMaybe = V.mapMaybe
 
 instance Witherable V.Vector where
   wither f = fmap V.fromList . wither f . V.toList
@@ -312,11 +339,35 @@
   wither f = fmap S.fromList . wither f . F.toList
   {-# INLINABLE wither #-}
 
+-- The instances for Compose, Product, and Sum are not entirely
+-- unique. Any particular composition, product, or sum of functors
+-- may support a variety of 'wither' implementations.
+
 instance (Functor f, Filterable g) => Filterable (Compose f g) where
   mapMaybe f = Compose . fmap (mapMaybe f) . getCompose
 
 instance (T.Traversable f, Witherable g) => Witherable (Compose f g) where
   wither f = fmap Compose . T.traverse (wither f) . getCompose
+
+instance (Filterable f, Filterable g) => Filterable (P.Product f g) where
+  mapMaybe f (P.Pair x y) = P.Pair (mapMaybe f x) (mapMaybe f y)
+
+instance (Witherable f, Witherable g) => Witherable (P.Product f g) where
+  wither f (P.Pair x y) = liftA2 P.Pair (wither f x) (wither f y)
+
+instance (Filterable f, Filterable g) => Filterable (Sum.Sum f g) where
+  mapMaybe f (Sum.InL x) = Sum.InL (mapMaybe f x)
+  mapMaybe f (Sum.InR y) = Sum.InR (mapMaybe f y)
+
+instance (Witherable f, Witherable g) => Witherable (Sum.Sum f g) where
+  wither f (Sum.InL x) = Sum.InL <$> wither f x
+  wither f (Sum.InR y) = Sum.InR <$> wither f y
+
+instance Filterable f => Filterable (IdentityT f) where
+  mapMaybe f (IdentityT m) = IdentityT (mapMaybe f m)
+
+instance Witherable f => Witherable (IdentityT f) where
+  wither f (IdentityT m) = IdentityT <$> wither f m
 
 instance Functor f => Filterable (MaybeT f) where
   mapMaybe f = MaybeT . fmap (mapMaybe f) . runMaybeT
diff --git a/witherable.cabal b/witherable.cabal
--- a/witherable.cabal
+++ b/witherable.cabal
@@ -1,5 +1,5 @@
 name:                witherable
-version:             0.2
+version:             0.3
 synopsis:            filterable traversable
 description:         A stronger variant of `traverse` which can remove elements and generalised mapMaybe, catMaybes, filter
 homepage:            https://github.com/fumieval/witherable
@@ -12,7 +12,7 @@
 build-type:          Simple
 -- extra-source-files:
 cabal-version:       >=1.10
-tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2
+tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3
 
 source-repository head
   type: git
@@ -24,9 +24,10 @@
   -- other-extensions:
   build-depends:       base == 4.*,
                        base-orphans,
-                       containers,
+                       containers >= 0.5,
                        hashable,
                        transformers,
+                       transformers-compat,
                        unordered-containers,
                        vector
   hs-source-dirs:      src
