diff --git a/predicate-transformers.cabal b/predicate-transformers.cabal
--- a/predicate-transformers.cabal
+++ b/predicate-transformers.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.4
 
 name: predicate-transformers
-version: 0.12.0.0
+version: 0.13.0.0
 synopsis: A library for writing predicates and transformations over predicates in Haskell
 description:
   This package provides ways to write predicates such that they compose nicely and are easy to debug.
diff --git a/src/PredicateTransformers.hs b/src/PredicateTransformers.hs
--- a/src/PredicateTransformers.hs
+++ b/src/PredicateTransformers.hs
@@ -5,6 +5,7 @@
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# OPTIONS_GHC -fexpose-all-unfoldings #-}
+{-# LANGUAGE ImpredicativeTypes #-}
 
 -- | This library is based on the notion of a predicate transformer, the below
 -- type @PT a b@, which is a function from @a@ to predicates on @b@.
@@ -34,6 +35,7 @@
 import Control.Concurrent (myThreadId, throwTo)
 import Control.Exception (SomeAsyncException)
 import GHC.Conc (pseq)
+import GHC.Stack
 
 -- | Class of possible predicate results.
 -- This is mostly a lattice with `otherHand` as disjunction, `also` as conjunction, `stop` as the falsy
@@ -41,16 +43,16 @@
 -- Note that test failure messages are not really the domain of this library.
 -- It's the author's hope that they can be mostly replaced by `traceFail`.
 class Predicatory a where
-  otherHand :: a -> a -> a
-  also :: a -> a -> a
-  stop :: a
+  otherHand :: HasCallStack => a -> a -> a
+  also :: HasCallStack => a -> a -> a
+  stop :: HasCallStack => a
   continue :: a
   {-# MINIMAL otherHand, also, stop, continue #-}
 
 instance Predicatory a => Predicatory (e -> a) where
   (f `otherHand` f') e = f e `otherHand` f' e
   (f `also` f') e = f e `also` f' e
-  stop = \_ -> stop
+  stop = withFrozenCallStack $ \_ -> stop
   continue = \_ -> continue
 
 infixr 3 `also`
@@ -65,10 +67,15 @@
   assess f act = \e -> assess (f e) act
 
 -- | The exception thrown by predicates of type `IO ()` by default. Other IOExceptions will work fine.
-data PredicateFailed = PredicateFailed
-  deriving (Show, Typeable)
+data PredicateFailed = PredicateFailed !CallStack
+  deriving (Typeable)
+instance Show PredicateFailed where
+  show = displayException
 
-instance Exception PredicateFailed
+instance Exception PredicateFailed where
+  displayException (PredicateFailed cs) =
+    "Predicate failed.\n" <>
+    prettyCallStack cs
 
 instance Predicatory Bool where
   otherHand = (||)
@@ -92,7 +99,7 @@
       , Handler $ \(_ex :: SomeException) -> y
       ]
   also = (>>)
-  stop = throwIO PredicateFailed
+  stop = throwIO (PredicateFailed callStack)
   continue = return ()
 
 instance Exceptional (IO ()) where
@@ -108,13 +115,13 @@
       ]
 
 -- | A convenient alias for predicates.
-type Pred a = a -> Bool
+type Pred p a = HasCallStack => a -> p
 
 -- | Predicate transformers form a category where composition is ordinary function composition.
 --  Forms a category with `.` and `id`.
 --  Multiple are already provided by the standard library,
 --  for instance `Data.Foldable.all` and `Data.Foldable.any`.
-type PT p a b = (a -> p) -> (b -> p)
+type PT p a b = HasCallStack => Pred p a -> Pred p b
 
 -- | Operate on the `Just` branch of a `Maybe`, or fail.
 just :: Predicatory p => PT p a (Maybe a)
@@ -139,7 +146,7 @@
 startingWith _ (toList -> []) = stop
 
 -- | Require that a @Fold@ has a single element, and operate on that element.
-soleElementOf :: Predicatory p => Fold s a -> PT p a s
+soleElementOf :: (Predicatory p) => Fold s a -> PT p a s
 soleElementOf f p (toListOf f -> [x]) = p x
 soleElementOf _ _ _ = stop
 
@@ -153,7 +160,7 @@
 
 -- | Given a list of predicates and a list of values, ensure that each predicate holds for each respective value.
 --  Fails if the two lists have different lengths.
-list :: Predicatory p => [a -> p] -> [a] -> p
+list :: Predicatory p => [Pred p a] -> [a] -> p
 list (p : ps) (x : xs) = p x `also` list ps xs
 list [] [] = continue
 list _ _ = stop
@@ -163,9 +170,8 @@
 --  Generalized version of `list`.
 dist ::
   (Predicatory p, Eq (f ()), Functor f, Foldable f) =>
-  f (a -> p) ->
-  f a ->
-  p
+  f (Pred p a) ->
+  Pred p (f a)
 dist preds values =
   bool stop continue ((() <$ preds) == (() <$ values))
     `also` list (toList preds) (toList values)
@@ -174,13 +180,13 @@
 --  yield a representable functor-full of booleans. Similar to `dist`.
 distRep ::
   Representable f =>
-  f (a -> p) ->
+  f (Pred p a) ->
   f a ->
   f p
 distRep pr fa = tabulate (\r -> index pr r $ index fa r)
 
 -- | Test all predicates against one value.
-allTrue :: (Predicatory p, Foldable f) => f (a -> p) -> a -> p
+allTrue :: (Predicatory p, Foldable f) => f (Pred p a) -> Pred p a
 allTrue ps a = foldr (\p r -> p a `also` r) continue ps
 
 -- | Check that a predicate is true for all values behind a generalized getter
@@ -194,18 +200,12 @@
 pattern a :=> b = (a, b)
 
 -- | A pair of predicates, made into a predicate on pairs.
-pair :: Predicatory p => (a -> p) -> (b -> p) -> (a, b) -> p
+pair :: Predicatory p => Pred p a -> Pred p b -> Pred p (a, b)
 pair f s (a, b) = f a `also` s b
 
--- | Flipped function composition; @f !@ for a function @f@ is a predicate transformer.
-(!) :: (b -> a) -> (a -> c) -> b -> c
-(!) = flip (.)
-infixr 8 !
-
--- | Higher precedence @$@, to work well with '!'.
-(?) :: (a -> b) -> a -> b
-(?) = ($)
-infixl 9 ?
+-- | Flipped function composition; @pt f@ for a function @f@ is a predicate transformer.
+pt :: (a -> b) -> PT p b a
+pt f p = p . f
 
 -- | Prints the input of a predicate, for debugging.
 traced :: Show a => (a -> String) -> PT c a a
@@ -227,18 +227,18 @@
   assess (p a) $ traceIO (s a)
 
 -- | Predicate which always succeeds.
-something :: Predicatory p => a -> p
+something :: Predicatory p => Pred p a
 something = const continue
 
 -- | Predicate which triggers full evaluation of its input and succeeds.
 --  Useful for testing that an exception isn't thrown.
-forced :: (Predicatory p, NFData a) => a -> p
+forced :: (Predicatory p, NFData a) => Pred p a
 forced a = force a `seq` continue
 
 -- | Predicate on equality.
-equals :: (Predicatory p, Eq a) => a -> a -> p
-equals a a' = bool stop continue (a == a')
+equals :: (Predicatory p, Eq a) => a -> Pred p a
+equals a a' = bool (stop a') continue (a == a')
 
 -- | Check that all of the input predicates are satisfied.
-satAll :: Predicatory p => [a -> p] -> a -> p
-satAll = foldr also continue
+satAll :: Predicatory p => [Pred p a] -> Pred p a
+satAll xs a = foldr (\p xs -> p a `also` xs) continue xs
