diff --git a/checkers.cabal b/checkers.cabal
--- a/checkers.cabal
+++ b/checkers.cabal
@@ -1,5 +1,5 @@
 Name:                checkers
-Version:             0.5.2
+Version:             0.5.4
 Cabal-Version:       >= 1.6
 Synopsis:            Check properties on standard classes and data structures.
 Category:            Testing
@@ -17,7 +17,7 @@
 License-File:        COPYING
 Stability:           experimental
 build-type:          Simple
-tested-with:         GHC==8.6.4, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3
+tested-with:         GHC==8.8.1, GHC==8.6.5, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3
 homepage:            https://github.com/conal/checkers
 source-repository head
   type:     git
diff --git a/src/Test/QuickCheck/Checkers.hs b/src/Test/QuickCheck/Checkers.hs
--- a/src/Test/QuickCheck/Checkers.hs
+++ b/src/Test/QuickCheck/Checkers.hs
@@ -33,7 +33,7 @@
   -- * Model-based (semantics-based) testing
   , Model(..)
   , meq, meq1, meq2, meq3, meq4, meq5
-  , eqModels
+  , eqModels, denotationFor
   , Model1(..)
   -- * Some handy testing types
   -- , Positive, NonZero(..), NonNegative(..)
@@ -44,7 +44,6 @@
   ) where
 
 import Data.Function (on)
-import Data.Monoid (Monoid (mempty, mappend))
 import Control.Applicative
 import Control.Arrow ((***),first)
 import qualified Control.Exception as Ex
@@ -231,6 +230,19 @@
 eqModels :: (Model a b, EqProp b) => a -> a -> Property
 eqModels = (=-=) `on` model
 
+
+-- | @f `'denotationFor'` g@ proves that @f@ is a model for @g@, ie that
+-- @'model' . g '=-=' f@.
+denotationFor
+    :: (Model b b', Arbitrary a, EqProp b', Show a)
+    => (a -> b')
+    -> (a -> b)
+    -> TestBatch
+denotationFor f g =
+  ( "denotation"
+  , [("eq", model . g =-= f)]
+  )
+
 -- Other types
 -- instance EqProp a => EqProp (S.Stream a) where (=-=) = eqModels
 
@@ -405,9 +417,12 @@
 instance Model Double Double where model = id
 instance Model String String where model = id
 
--- This next one requires UndecidableInstances
+-- These next two require UndecidableInstances
 instance (Model a b, Model a' b') => Model (a,a') (b,b') where
   model = model *** model
+
+instance Model b b' => Model (a -> b) (a -> b') where
+  model f = model . f
 
 -- instance Model (S.Stream a) (NonNegative Int -> a) where
 --   model s (NonNegative i) = s S.!! i
diff --git a/src/Test/QuickCheck/Classes.hs b/src/Test/QuickCheck/Classes.hs
--- a/src/Test/QuickCheck/Classes.hs
+++ b/src/Test/QuickCheck/Classes.hs
@@ -2,12 +2,6 @@
            , Rank2Types, TypeOperators, CPP
   #-}
 
-{-# OPTIONS_GHC -Wall #-}
-
-#if MIN_VERSION_base(4,9,0)
--- https://github.com/conal/checkers/pull/38
-{-# OPTIONS_GHC -Wno-redundant-constraints #-}
-#endif
 ----------------------------------------------------------------------
 -- |
 -- Module      :  Test.QuickCheck.Classes
@@ -34,7 +28,6 @@
   )
   where
 
-import Control.Applicative ((<$>))
 import Data.Foldable (Foldable(..))
 import Data.Functor.Apply (Apply ((<.>)))
 import Data.Functor.Alt (Alt ((<!>)))
@@ -42,9 +35,9 @@
 import qualified Data.Functor.Bind as B (Bind (join))
 import Data.List.NonEmpty (NonEmpty(..))
 import Data.Semigroup (Semigroup (..))
-import Data.Monoid (Monoid (mappend, mempty), Endo(..), Dual(..), Sum(..), Product(..))
-import Data.Traversable (Traversable (..), fmapDefault, foldMapDefault)
-import Control.Applicative
+import Data.Monoid (Endo(..), Dual(..), Sum(..), Product(..))
+import Data.Traversable (fmapDefault, foldMapDefault)
+import Control.Applicative (Alternative(..))
 import Control.Monad (MonadPlus (..), ap, join)
 import Control.Arrow (Arrow,ArrowChoice,first,second,left,right,(>>>),arr)
 import Test.QuickCheck
@@ -745,6 +738,9 @@
 -- | Note that 'foldable' doesn't check the strictness of 'foldl'', `foldr'' and `foldMap''.
 --
 -- @since 0.4.13
+
+-- The (Arbitrary m) constraint is required with base >= 4.13, where we have an
+-- additional property for checking foldMap'.
 foldable :: forall t a b m n o.
             ( Foldable t
             , CoArbitrary a, CoArbitrary b
diff --git a/src/Test/QuickCheck/Instances/Array.hs b/src/Test/QuickCheck/Instances/Array.hs
--- a/src/Test/QuickCheck/Instances/Array.hs
+++ b/src/Test/QuickCheck/Instances/Array.hs
@@ -10,6 +10,7 @@
 import Test.QuickCheck
 import Data.Array
 
+-- The redundant (Ix a) constraint is required with GHC-7.10.
 instance (Ix a, Integral a, Arbitrary b) => Arbitrary (Array a b) where
   arbitrary   =
     (\x -> listArray (0,fromIntegral (length x - 1)) x) <$> arbitrary
diff --git a/src/Test/QuickCheck/Instances/Maybe.hs b/src/Test/QuickCheck/Instances/Maybe.hs
--- a/src/Test/QuickCheck/Instances/Maybe.hs
+++ b/src/Test/QuickCheck/Instances/Maybe.hs
@@ -1,6 +1,5 @@
 module Test.QuickCheck.Instances.Maybe (maybeGen) where
 
-import Control.Applicative (pure, (<$>))
 import Test.QuickCheck
 
 maybeGen :: Gen a -> Gen (Maybe a)
diff --git a/src/Test/QuickCheck/Instances/Num.hs b/src/Test/QuickCheck/Instances/Num.hs
--- a/src/Test/QuickCheck/Instances/Num.hs
+++ b/src/Test/QuickCheck/Instances/Num.hs
@@ -4,7 +4,6 @@
        ,nonZero,nonZero_
        ) where
 
-import Control.Applicative ((<$>))
 import Test.QuickCheck
 import Control.Monad.Extensions
 
