diff --git a/Language/KURE/Combinators.hs b/Language/KURE/Combinators.hs
--- a/Language/KURE/Combinators.hs
+++ b/Language/KURE/Combinators.hs
@@ -25,18 +25,21 @@
            , notM
            , modFailMsg
            , setFailMsg
+           , prefixFailMsg
            , withPatFailMsg
              -- ** Conditionals
            , guardMsg
            , guardM
-           , condM
+           , ifM
            , whenM
+           , unlessM
              -- * Arrow Combinators
              -- ** Categories with a Catch
            , CategoryCatch(..)
            , (<+)
            , readerT
            , acceptR
+           , accepterR
            , tryR
            , attemptR
            , changedR
@@ -55,6 +58,7 @@
            , fork
            , forkFirst
            , forkSecond
+           , constant
 ) where
 
 import Prelude hiding (id , (.), catch)
@@ -107,7 +111,7 @@
 
 -- | Fail if the 'Monad' succeeds; succeed with @()@ if it fails.
 notM :: MonadCatch m => m a -> m ()
-notM ma = condM (testM ma) (fail "notM  of success") (return ())
+notM ma = ifM (testM ma) (fail "notM of success") (return ())
 
 -- | Modify the error message of a failing monadic computation.
 --   Successful computations are unaffected.
@@ -119,6 +123,11 @@
 setFailMsg :: MonadCatch m => String -> m a -> m a
 setFailMsg msg = modFailMsg (const msg)
 
+-- | Add a prefix to the error message of a failing monadic computation.
+--   Successful computations are unaffected.
+prefixFailMsg :: MonadCatch m => String -> m a -> m a
+prefixFailMsg msg = modFailMsg (msg ++)
+
 -- | Use the given error message whenever a monadic pattern match failure occurs.
 withPatFailMsg :: MonadCatch m => String -> m a -> m a
 withPatFailMsg msg = modFailMsg (\ e -> if "Pattern match failure" `isPrefixOf` e then msg else e)
@@ -131,17 +140,21 @@
 
 -- | As 'guardMsg', but with a default error message.
 guardM ::  Monad m => Bool -> m ()
-guardM b = guardMsg b "guard failed"
+guardM b = guardMsg b "guardM failed"
 
--- | if-then-else lifted over a 'Monad'.
-condM ::  Monad m => m Bool -> m a -> m a -> m a
-condM mb m1 m2 = do b <- mb
-                    if b then m1 else m2
+-- | if-then-else lifted over a monadic predicate.
+ifM ::  Monad m => m Bool -> m a -> m a -> m a
+ifM mb m1 m2 = do b <- mb
+                  if b then m1 else m2
 
--- | if-then lifted over a 'Monad'.
+-- | If the monadic predicate holds then perform the monadic action, else fail.
 whenM ::  Monad m => m Bool -> m a -> m a
-whenM mb ma = condM mb ma (fail "condition False")
+whenM mb ma = ifM mb ma (fail "whenM: condition False")
 
+-- | If the monadic predicate holds then fail, else perform the monadic action.
+unlessM ::  Monad m => m Bool -> m a -> m a
+unlessM mb ma = ifM mb (fail "unlessM: condition True") ma
+
 ------------------------------------------------------------------------------------------
 
 -- | 'Category's with failure and catching.
@@ -166,9 +179,14 @@
 readerT f = (f &&& id) ^>> app
 
 -- | Look at the argument to an 'Arrow', and choose to be either the identity arrow or a failure.
-acceptR :: (CategoryCatch (~>), ArrowApply (~>)) => (a -> Bool) -> (a ~> a)
-acceptR p = readerT $ \ a -> if p a then id else failT "acceptR: predicate failed"
+acceptR :: (CategoryCatch (~>), ArrowApply (~>)) => (a -> Bool) -> String -> (a ~> a)
+acceptR p msg = readerT $ \ a -> if p a then id else failT msg
 
+-- | Look at the argument to an 'Arrow', and choose to be either the identity arrow or a failure.
+--   This is a generalisation of 'acceptR' to any 'Arrow'.
+accepterR :: (CategoryCatch (~>), ArrowApply (~>)) => (a ~> Bool) -> String -> (a ~> a)
+accepterR t msg = forkFirst t >>> readerT (\ (b,a) -> if b then constant a else failT msg)
+
 -- | Catch a failing 'CategoryCatch', making it into an identity.
 tryR :: CategoryCatch (~>) => (a ~> a) -> (a ~> a)
 tryR r = r <+ id
@@ -180,7 +198,7 @@
 
 -- | Makes an 'Arrow' fail if the result value equals the argument value.
 changedR :: (CategoryCatch (~>), ArrowApply (~>), Eq a) => (a ~> a) -> (a ~> a)
-changedR r = readerT (\ a -> r >>> acceptR (/=a))
+changedR r = readerT (\ a -> r >>> acceptR (/=a) "changedR: value is unchanged")
 
 -- | Repeat a 'CategoryCatch' until it fails, then return the result before the failure.
 --   Requires at least the first attempt to succeed.
@@ -236,5 +254,9 @@
 -- | Tag the result of an 'Arrow' with its argument.
 forkSecond :: Arrow (~>) => (a ~> b) -> (a ~> (a , b))
 forkSecond sf = fork >>> second sf
+
+-- | An arrow with a constant result.
+constant :: Arrow (~>) => b -> (a ~> b)
+constant b = arr (const b)
 
 -------------------------------------------------------------------------------
diff --git a/Language/KURE/Walker.hs b/Language/KURE/Walker.hs
--- a/Language/KURE/Walker.hs
+++ b/Language/KURE/Walker.hs
@@ -349,12 +349,12 @@
 
 -- | Find the 'Path's to every 'Node' that satisfies the predicate.
 pathsToT :: (PathContext c, Walker c m a, a ~ Generic a) => (Generic a -> Bool) -> Translate c m (Generic a) [Path]
-pathsToT q = collectT (acceptR q >>> absPathT) >>= mapM abs2pathT
+pathsToT q = collectT (acceptR q "pathsToT" >>> absPathT) >>= mapM abs2pathT
 
 -- | Find the 'Path' to the first 'Node' that satisfies the predicate (in a pre-order traversal).
 onePathToT :: (PathContext c, Walker c m a, a ~ Generic a) => (Generic a -> Bool) -> Translate c m (Generic a) Path
 onePathToT q = setFailMsg "No matching nodes found." $
-               onetdT (acceptR q >>> absPathT) >>= abs2pathT
+               onetdT (acceptR q "pathsToT" >>> absPathT) >>= abs2pathT
 
 -- | Find the 'Path' to the first descendent 'Node' that satisfies the predicate (in a pre-order traversal).
 oneNonEmptyPathToT :: (PathContext c, Walker c m a, a ~ Generic a) => (Generic a -> Bool) -> Translate c m (Generic a) Path
@@ -364,7 +364,7 @@
 
 -- | Find the 'Path's to every 'Node' that satisfies the predicate, ignoring 'Node's below successes.
 prunePathsToT :: (PathContext c, Walker c m a, a ~ Generic a) => (Generic a -> Bool) -> Translate c m (Generic a) [Path]
-prunePathsToT q = collectPruneT (acceptR q >>> absPathT) >>= mapM abs2pathT
+prunePathsToT q = collectPruneT (acceptR q "pathsToT" >>> absPathT) >>= mapM abs2pathT
 
 
 -- local function used by uniquePathToT and uniquePrunePathToT
diff --git a/kure.cabal b/kure.cabal
--- a/kure.cabal
+++ b/kure.cabal
@@ -1,5 +1,5 @@
 Name:                kure
-Version:             2.2.0
+Version:             2.4.0
 Synopsis:            Combinators for Strategic Programming
 Description:	     The Kansas University Rewrite Engine (KURE) is a DSL for strategic rewriting.
 	 	     KURE shares concepts with Stratego, but unlike Stratego, KURE is strongly typed.
