diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+0.3.5
+-------
+
+* Make `wither` and `witherM` methods of `Witherable []` instance
+  good consumers for list fusion.
+* Added instances for `Reverse`, `Backwards`, `ZipList`, and types from `GHC.Generics`
+* Added `Wither`, `WitherLike`, `Wither'` and `WitherLike'`, deprecating `Filter` and the variants
+* Moved `Filterable` and `Witherable` into a separate package, `witherable-class`
+
+0.3.4
+-------
+* Exported `WrappedFoldable`
+
 0.3.3
 -------
 
diff --git a/src/Data/Witherable.hs b/src/Data/Witherable.hs
--- a/src/Data/Witherable.hs
+++ b/src/Data/Witherable.hs
@@ -4,9 +4,7 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
-#if __GLASGOW_HASKELL__ >= 702
-{-# LANGUAGE Trustworthy #-}
-#endif
+{-# LANGUAGE EmptyCase #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Witherable
@@ -30,6 +28,7 @@
   , FilterableWithIndex(..)
   , WitherableWithIndex(..)
   -- * Generalization
+  , WitherLike, Wither, WitherLike', Wither'
   , FilterLike, Filter, FilterLike', Filter'
   , witherOf
   , forMaybeOf
@@ -48,7 +47,7 @@
 
 where
 import qualified Control.Lens as Lens
-import qualified Data.Maybe as Maybe
+import Data.Witherable.Class
 import qualified Data.IntMap.Lazy as IM
 import qualified Data.Map.Lazy as M
 import qualified Data.Map.Monoidal as MM
@@ -66,29 +65,37 @@
 import Control.Monad.Trans.Identity
 import Data.Hashable
 import Data.Functor.Identity
-import Control.Monad.Trans.Maybe
+import Data.Functor.Reverse (Reverse (..))
+import Control.Applicative.Backwards (Backwards (..))
 import Control.Monad.Trans.State.Strict
 import Data.Monoid
 import Data.Orphans ()
-#if (MIN_VERSION_base(4,7,0))
 import Data.Proxy
 import Data.Void
-#endif
 import Data.Coerce (coerce)
-import Prelude -- Fix redundant import warning
+import Prelude hiding (filter)
 
+type Filter s t a b = Wither s t a b
+{-# DEPRECATED Filter "Use Wither instead" #-}
+type FilterLike f s t a b = WitherLike f s t a b
+{-# DEPRECATED FilterLike "Use WitherLike instead" #-}
+type Filter' s a = Wither' s a
+{-# DEPRECATED Filter' "Use Filter' instead" #-}
+type FilterLike' f s a = WitherLike' f s a
+{-# DEPRECATED FilterLike' "Use WitherLike' instead" #-}
+
 -- | This type allows combinators to take a 'Filter' specializing the parameter @f@.
-type FilterLike f s t a b = (a -> f (Maybe b)) -> s -> f t
+type WitherLike f s t a b = (a -> f (Maybe b)) -> s -> f t
 
--- | A 'Filter' is like a <http://hackage.haskell.org/package/lens-4.13.2.1/docs/Control-Lens-Type.html#t:Traversal Traversal>,
+-- | A 'Wither' is like a <http://hackage.haskell.org/package/lens-4.13.2.1/docs/Control-Lens-Type.html#t:Traversal Traversal>,
 -- but you can also remove targets.
-type Filter s t a b = forall f. Applicative f => FilterLike f s t a b
+type Wither s t a b = forall f. Applicative f => WitherLike f s t a b
 
--- | A simple 'FilterLike'.
-type FilterLike' f s a = FilterLike f s s a a
+-- | A simple 'WitherLike'.
+type WitherLike' f s a = WitherLike f s s a a
 
--- | A simple 'Filter'.
-type Filter' s a = forall f. Applicative f => FilterLike' f s a
+-- | A simple 'Wither'.
+type Wither' s a = forall f. Applicative f => WitherLike' f s a
 
 -- | This is used to characterize and clone a 'Filter'.
 -- Since @FilterLike (Peat a b) s t a b@ is monomorphic, it can be used to store a filter in a container.
@@ -127,11 +134,7 @@
 -- 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
@@ -153,37 +156,6 @@
 filterOf w f = runIdentity . filterAOf w (idDot f)
 {-# INLINE filterOf #-}
 
--- | Like 'Functor', but you can remove elements instead of updating them.
---
--- Formally, the class 'Filterable' represents a functor from @Kleisli Maybe@ to @Hask@.
---
--- A definition of 'mapMaybe' must satisfy the following laws:
---
--- [/conservation/]
---   @'mapMaybe' (Just . f) ≡ 'fmap' f@
---
--- [/composition/]
---   @'mapMaybe' f . 'mapMaybe' g ≡ 'mapMaybe' (f <=< g)@
-class Functor f => Filterable f where
-  -- | Like 'Maybe.mapMaybe'.
-  mapMaybe :: (a -> Maybe b) -> f a -> f b
-  mapMaybe f = catMaybes . fmap f
-  {-# INLINE mapMaybe #-}
-
-  -- | @'catMaybes' ≡ 'mapMaybe' 'id'@
-  catMaybes :: f (Maybe a) -> f a
-  catMaybes = mapMaybe id
-  {-# INLINE catMaybes #-}
-
-  -- | @'filter' f . 'filter' g ≡ filter ('liftA2' ('&&') f g)@
-  filter :: (a -> Bool) -> f a -> f a
-  filter f = mapMaybe $ \a -> if f a then Just a else Nothing
-  {-# INLINE filter #-}
-
-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707
-  {-# MINIMAL mapMaybe | catMaybes #-}
-#endif
-
 -- | An infix alias for 'mapMaybe'. The name of the operator alludes
 -- to '<$>', and has the same fixity.
 --
@@ -215,48 +187,6 @@
   ifilter f = imapMaybe $ \i a -> if f i a then Just a else Nothing
   {-# INLINE ifilter #-}
 
--- | An enhancement of 'Traversable' with 'Filterable'
---
--- A definition of 'wither' must satisfy the following laws:
---
--- [/conservation/]
---   @'wither' ('fmap' 'Just' . f) ≡ 'traverse' f@
---
--- [/composition/]
---   @'Compose' . 'fmap' ('wither' f) . 'wither' g ≡ 'wither' ('Compose' . 'fmap' ('wither' f) . g)@
---
--- Parametricity implies the naturality law:
---
---   @t . 'wither' f ≡ 'wither' (t . f)@
---
-
-class (T.Traversable t, Filterable t) => Witherable t where
-
-  -- | Effectful 'mapMaybe'.
-  --
-  -- @'wither' ('pure' . f) ≡ 'pure' . 'mapMaybe' f@
-  wither :: Applicative f => (a -> f (Maybe b)) -> t a -> f (t b)
-  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 #-}
-
-  filterA :: Applicative f => (a -> f Bool) -> t a -> f (t a)
-  filterA = filterAOf wither
-
-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707
-  {-# MINIMAL #-}
-#endif
-
 -- | @'forMaybe' = 'flip' 'wither'@
 forMaybe :: (Witherable t, Applicative f) => t a -> (a -> f (Maybe b)) -> f (t b)
 forMaybe = flip wither
@@ -272,13 +202,7 @@
 
   -- | @Monadic variant of 'wither'. This may have more efficient implementation.@
   iwitherM :: (Monad m) => (i -> a -> m (Maybe b)) -> t a -> m (t b)
-#if MIN_VERSION_base(4,8,0)
   iwitherM = iwither
-#elif __GLASGOW_HASKELL__ >= 708
-  iwitherM f = unwrapMonad . iwither (coerce f)
-#else
-  iwitherM f = unwrapMonad . iwither (\i -> WrapMonad . f i)
-#endif
 
   ifilterA :: (Applicative f) => (i -> a -> f Bool) -> t a -> f (t a)
   ifilterA f = iwither (\i a -> (\b -> if b then Just a else Nothing) <$> f i a)
@@ -317,8 +241,8 @@
 {-# INLINE hashNub #-}
 
 -- | A default implementation for 'mapMaybe'.
-mapMaybeDefault :: (Foldable f, Alternative f) => (a -> Maybe b) -> f a -> f b
-mapMaybeDefault p = foldr (\x xs -> case p x of
+mapMaybeDefault :: (F.Foldable f, Alternative f) => (a -> Maybe b) -> f a -> f b
+mapMaybeDefault p = F.foldr (\x xs -> case p x of
     Just a -> pure a <|> xs
     _ -> xs) empty
 {-# INLINABLE mapMaybeDefault #-}
@@ -331,7 +255,7 @@
 {-# INLINABLE imapMaybeDefault #-}
 
 newtype WrappedFoldable f a = WrapFilterable {unwrapFoldable :: f a}
-  deriving (Functor, Foldable, Traversable, Applicative, Alternative)
+  deriving (Functor, F.Foldable, T.Traversable, Applicative, Alternative)
 
 instance (Lens.FunctorWithIndex i f) => Lens.FunctorWithIndex i (WrappedFoldable f) where
   imap f = WrapFilterable . Lens.imap f . unwrapFoldable
@@ -342,7 +266,7 @@
 instance (Lens.TraversableWithIndex i f) => Lens.TraversableWithIndex i (WrappedFoldable f) where
   itraverse f = fmap WrapFilterable . Lens.itraverse f . unwrapFoldable
 
-instance (Foldable f, Alternative f) => Filterable (WrappedFoldable f) where
+instance (F.Foldable f, Alternative f) => Filterable (WrappedFoldable f) where
     {-#INLINE mapMaybe#-}
     mapMaybe = mapMaybeDefault
 
@@ -350,71 +274,34 @@
   {-# INLINE imapMaybe #-}
   imapMaybe = imapMaybeDefault
 
-instance Filterable Maybe where
-  mapMaybe f = (>>= f)
-  {-# INLINE mapMaybe #-}
-
 instance FilterableWithIndex () Maybe
 
-instance Witherable Maybe where
-  wither _ Nothing = pure Nothing
-  wither f (Just a) = f a
-  {-# INLINABLE wither #-}
-
 instance WitherableWithIndex () Maybe
 
-instance Monoid e => Filterable (Either e) where
-  mapMaybe _ (Left e) = Left e
-  mapMaybe f (Right a) = maybe (Left mempty) Right $ f a
-  {-# INLINABLE mapMaybe #-}
-
-instance Monoid e => Witherable (Either e) where
-  wither _ (Left e) = pure (Left e)
-  wither f (Right a) = fmap (maybe (Left mempty) Right) (f a)
-  {-# INLINABLE wither #-}
-
-instance Filterable [] where
-  mapMaybe = Maybe.mapMaybe
-  catMaybes = Maybe.catMaybes
-  filter = Prelude.filter
+-- Option doesn't have the necessary instances in Lens
+--instance FilterableWithIndex () Option
+--instance WitherableWithIndex () Option
 
 instance FilterableWithIndex Int []
 
-instance (Alternative f, Traversable f) => Witherable (WrappedFoldable f)
+instance FilterableWithIndex Int ZipList
 
-instance Witherable [] where
-  wither f = go where
-    go (x:xs) = liftA2 (maybe id (:)) (f x) (go xs)
-    go [] = pure []
-  {-# INLINE[0] wither #-}
+instance (Alternative f, T.Traversable f) => Witherable (WrappedFoldable f)
 
 instance WitherableWithIndex Int []
 
-instance Filterable IM.IntMap where
-  mapMaybe = IM.mapMaybe
-  filter = IM.filter
+instance WitherableWithIndex Int ZipList
 
 instance FilterableWithIndex Int IM.IntMap where
   imapMaybe = IM.mapMaybeWithKey
   ifilter = IM.filterWithKey
 
-instance Witherable IM.IntMap where
-
 instance WitherableWithIndex Int IM.IntMap where
 
-instance Filterable (M.Map k) where
-  mapMaybe = M.mapMaybe
-  filter = M.filter
-
 instance FilterableWithIndex k (M.Map k) where
   imapMaybe = M.mapMaybeWithKey
   ifilter = M.filterWithKey
 
-instance Witherable (M.Map k) where
-#if MIN_VERSION_containers(0,5,8)
-  wither f = M.traverseMaybeWithKey (const f)
-#endif
-
 instance WitherableWithIndex k (M.Map k) where
 #if MIN_VERSION_containers(0,5,8)
   iwither = M.traverseMaybeWithKey
@@ -424,129 +311,88 @@
   mapMaybe = MM.mapMaybe
   filter = MM.filter
 
+instance Witherable (MM.MonoidalMap k)
+
 instance FilterableWithIndex k (MM.MonoidalMap k) where
   imapMaybe = MM.mapMaybeWithKey
   ifilter = MM.filterWithKey
 
-instance Witherable (MM.MonoidalMap k)
-
 instance WitherableWithIndex k (MM.MonoidalMap k)
 
-instance (Eq k, Hashable k) => Filterable (HM.HashMap k) where
-  mapMaybe = HM.mapMaybe
-  filter = HM.filter
-
 instance (Eq k, Hashable k) => FilterableWithIndex k (HM.HashMap k) where
   imapMaybe = HM.mapMaybeWithKey
   ifilter = HM.filterWithKey
 
-instance (Eq k, Hashable k) => Witherable (HM.HashMap k) where
-
 instance (Eq k, Hashable k) => WitherableWithIndex k (HM.HashMap k) where
 
-#if (MIN_VERSION_base(4,7,0))
-instance Filterable Proxy where
- mapMaybe _ Proxy = Proxy
-
 instance FilterableWithIndex Void Proxy
 
-instance Witherable Proxy where
-  wither _ Proxy = pure Proxy
-
 instance WitherableWithIndex Void Proxy
-#endif
 
-instance Filterable (Const r) where
-  mapMaybe _ (Const r) = Const r
-  {-# INLINABLE mapMaybe #-}
-
-instance Witherable (Const r) where
-  wither _ (Const r) = pure (Const r)
-  {-# INLINABLE wither #-}
-
-instance Filterable V.Vector where
-  mapMaybe = V.mapMaybe
-
 instance FilterableWithIndex Int V.Vector where
   imapMaybe = V.imapMaybe
   ifilter = V.ifilter
 
-instance Witherable V.Vector where
-  wither f = fmap V.fromList . wither f . V.toList
-  {-# INLINABLE wither #-}
-
 instance WitherableWithIndex Int V.Vector
 
-instance Filterable S.Seq where
-  mapMaybe f = S.fromList . mapMaybe f . F.toList
-  {-# INLINABLE mapMaybe #-}
-
 instance FilterableWithIndex Int S.Seq
 
-instance Witherable S.Seq where
-  wither f = fmap S.fromList . wither f . F.toList
-  {-# INLINABLE wither #-}
-
 instance WitherableWithIndex Int S.Seq
 
--- 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 (Lens.FunctorWithIndex i f, FilterableWithIndex j g) => FilterableWithIndex (i, j) (Compose f g) where
   imapMaybe f = Compose . Lens.imap (\i -> imapMaybe (\j -> f (i, j))) . getCompose
-
-instance (T.Traversable f, Witherable g) => Witherable (Compose f g) where
-  wither f = fmap Compose . T.traverse (wither f) . getCompose
+  ifilter p = Compose . Lens.imap (\i -> ifilter (\j -> p (i, j))) . getCompose
 
 instance (Lens.TraversableWithIndex i f, WitherableWithIndex j g) => WitherableWithIndex (i, j) (Compose f g) where
   iwither f = fmap Compose . Lens.itraverse (\i -> iwither (\j -> f (i, j))) . 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)
+  iwitherM f = fmap Compose . Lens.imapM (\i -> iwitherM (\j -> f (i, j))) . getCompose
+  ifilterA p = fmap Compose . Lens.itraverse (\i -> ifilterA (\j -> p (i, j))) . getCompose
 
 instance (FilterableWithIndex i f, FilterableWithIndex j g) => FilterableWithIndex (Either i j) (P.Product f g) where
   imapMaybe f (P.Pair x y) = P.Pair (imapMaybe (f . Left) x) (imapMaybe (f . Right) 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)
+  ifilter p (P.Pair x y) = P.Pair (ifilter (p . Left) x) (ifilter (p . Right) y)
 
 instance (WitherableWithIndex i f, WitherableWithIndex j g) => WitherableWithIndex (Either i j) (P.Product f g) where
-  iwither f (P.Pair x y) = P.Pair <$> iwither (f . Left) x <*> iwither (f . Right) 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)
+  iwither f (P.Pair x y) = liftA2 P.Pair (iwither (f . Left) x) (iwither (f . Right) y)
+  iwitherM f (P.Pair x y) = liftA2 P.Pair (iwitherM (f . Left) x) (iwitherM (f . Right) y)
+  ifilterA p (P.Pair x y) = liftA2 P.Pair (ifilterA (p . Left) x) (ifilterA (p . Right) y)
 
 instance (FilterableWithIndex i f, FilterableWithIndex j g) => FilterableWithIndex (Either i j) (Sum.Sum f g) where
   imapMaybe f (Sum.InL x) = Sum.InL (imapMaybe (f . Left) x)
   imapMaybe f (Sum.InR y) = Sum.InR (imapMaybe (f . Right) 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
+  ifilter f (Sum.InL x) = Sum.InL (ifilter (f . Left) x)
+  ifilter f (Sum.InR y) = Sum.InR (ifilter (f . Right) y)
 
 instance (WitherableWithIndex i f, WitherableWithIndex j g) => WitherableWithIndex (Either i j) (Sum.Sum f g) where
   iwither f (Sum.InL x) = Sum.InL <$> iwither (f . Left) x
   iwither f (Sum.InR y) = Sum.InR <$> iwither (f . Right) y
 
-instance Filterable f => Filterable (IdentityT f) where
-  mapMaybe f (IdentityT m) = IdentityT (mapMaybe f m)
+  iwitherM f (Sum.InL x) = Sum.InL <$> iwitherM (f . Left) x
+  iwitherM f (Sum.InR y) = Sum.InR <$> iwitherM (f . Right) y
 
-instance (FilterableWithIndex i f) => FilterableWithIndex i (IdentityT f) where
-  imapMaybe f (IdentityT m) = IdentityT (imapMaybe f m)
+  ifilterA f (Sum.InL x) = Sum.InL <$> ifilterA (f . Left) x
+  ifilterA f (Sum.InR y) = Sum.InR <$> ifilterA (f . Right) y
 
-instance Witherable f => Witherable (IdentityT f) where
-  wither f (IdentityT m) = IdentityT <$> wither f m
+deriving instance (FilterableWithIndex i f) => FilterableWithIndex i (IdentityT f)
 
 instance (WitherableWithIndex i f) => WitherableWithIndex i (IdentityT f) where
   iwither f (IdentityT m) = IdentityT <$> iwither f m
+  iwitherM f (IdentityT m) = IdentityT <$> iwitherM f m
+  ifilterA p (IdentityT m) = IdentityT <$> ifilterA p m
 
-instance Functor f => Filterable (MaybeT f) where
-  mapMaybe f = MaybeT . fmap (mapMaybe f) . runMaybeT
+deriving instance FilterableWithIndex i t => FilterableWithIndex i (Reverse t)
 
-instance (T.Traversable t) => Witherable (MaybeT t) where
-  wither f = fmap MaybeT . T.traverse (wither f) . runMaybeT
+-- | Wither from right to left.
+instance WitherableWithIndex i t => WitherableWithIndex i (Reverse t) where
+  iwither f (Reverse t) = fmap Reverse . forwards $ iwither (\i -> Backwards . f i) t
+  -- We can't do anything special with iwitherM, because Backwards m is not
+  -- generally a Monad.
+  ifilterA p (Reverse t) = fmap Reverse . forwards $ ifilterA (\i -> Backwards . p i) t
+
+deriving instance FilterableWithIndex i t => FilterableWithIndex i (Backwards t)
+
+instance WitherableWithIndex i t => WitherableWithIndex i (Backwards t) where
+  iwither f (Backwards xs) = Backwards <$> iwither f xs
+  iwitherM f (Backwards xs) = Backwards <$> iwitherM f xs
+  ifilterA f (Backwards xs) = Backwards <$> ifilterA f xs
diff --git a/witherable.cabal b/witherable.cabal
--- a/witherable.cabal
+++ b/witherable.cabal
@@ -1,5 +1,5 @@
 name:                witherable
-version:             0.3.4
+version:             0.3.5
 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:  CHANGELOG.md
 cabal-version:       >=1.10
-tested-With: GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.3
+tested-With: GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.3, GHC == 8.8.1
 
 source-repository head
   type: git
@@ -31,7 +31,12 @@
                        transformers,
                        transformers-compat,
                        unordered-containers,
-                       vector
+                       vector,
+                       witherable-class
+  if impl(ghc < 7.9)
+    build-depends:     void
   hs-source-dirs:      src
-  ghc-options:         -Wall -Wcompat
+  ghc-options:         -Wall
   default-language:    Haskell2010
+  if (impl(ghc>=8))
+    ghc-options:       -Wcompat
