diff --git a/ClassyPrelude.hs b/ClassyPrelude.hs
--- a/ClassyPrelude.hs
+++ b/ClassyPrelude.hs
@@ -7,6 +7,7 @@
     ( -- * CorePrelude
       module CorePrelude
     , Seq
+    , undefined
       -- * Standard
       -- ** Monoid
     , empty
@@ -112,6 +113,13 @@
       -- ** Chunking
     , toChunks
     , fromChunks
+      -- ** Exceptions
+    , catchAny
+    , handleAny
+    , tryAny
+    , catchIO
+    , handleIO
+    , tryIO
       -- ** Force types
       -- | Helper functions for situations where type inferer gets confused.
     , asByteString
@@ -125,10 +133,13 @@
     , asMaybe
     , asSet
     , asVector
+    , asIOException
+    , asSomeException
     ) where
 
 import qualified Prelude
 import Control.Monad (when, unless, void, liftM, ap, forever, join, sequence, sequence_)
+import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Concurrent.MVar.Lifted
 import Data.IORef.Lifted
 import Data.Monoid (Monoid)
@@ -136,7 +147,7 @@
 import Data.Foldable (Foldable)
 import qualified Data.Foldable as Foldable
 
-import CorePrelude hiding (print)
+import CorePrelude hiding (print, undefined)
 import ClassyPrelude.Classes
 
 import ClassyPrelude.ByteString ()
@@ -181,10 +192,6 @@
 append = mappend
 {-# INLINE append #-}
 
-empty :: Monoid m => m
-empty = mempty
-{-# INLINE empty #-}
-
 infixr 5  ++
 (++) :: Monoid m => m -> m -> m
 (++) = mappend
@@ -276,3 +283,71 @@
 -- Inspired by <http://hackage.haskell.org/packages/archive/base/latest/doc/html/GHC-Exts.html#v:groupWith>
 groupWith :: (CanGroupBy c a, Eq b) => (a -> b) -> c -> [c]
 groupWith f = groupBy (\a b -> f a == f b)
+
+-- | We define our own @undefined@ which is marked as deprecated. This makes it
+-- useful to use during development, but let's you more easily getting
+-- notification if you accidentally ship partial code in production.
+--
+-- The classy prelude recommendation for when you need to really have a partial
+-- function in production is to use @error@ with a very descriptive message so
+-- that, in case an exception is thrown, you get more information than
+-- @Prelude.undefined@.
+--
+-- Since 0.5.5
+undefined :: a
+undefined = error "ClassyPrelude.undefined"
+{-# DEPRECATED undefined "It is highly recommended that you either avoid partial functions or provide meaningful error messages" #-}
+
+-- | A version of 'catch' which is specialized for any exception. This
+-- simplifies usage as no explicit type signatures are necessary.
+--
+-- Since 0.5.6
+catchAny :: MonadBaseControl IO m => m a -> (SomeException -> m a) -> m a
+catchAny = catch
+
+-- | A version of 'handle' which is specialized for any exception.  This
+-- simplifies usage as no explicit type signatures are necessary.
+--
+-- Since 0.5.6
+handleAny :: MonadBaseControl IO m => (SomeException -> m a) -> m a -> m a
+handleAny = handle
+
+-- | A version of 'try' which is specialized for any exception.
+-- This simplifies usage as no explicit type signatures are necessary.
+--
+-- Since 0.5.6
+tryAny :: MonadBaseControl IO m => m a -> m (Either SomeException a)
+tryAny = try
+
+-- | A version of 'catch' which is specialized for IO exceptions. This
+-- simplifies usage as no explicit type signatures are necessary.
+--
+-- Since 0.5.6
+catchIO :: MonadBaseControl IO m => m a -> (IOException -> m a) -> m a
+catchIO = catch
+
+-- | A version of 'handle' which is specialized for IO exceptions.  This
+-- simplifies usage as no explicit type signatures are necessary.
+--
+-- Since 0.5.6
+handleIO :: MonadBaseControl IO m => (IOException -> m a) -> m a -> m a
+handleIO = handle
+
+-- | A version of 'try' which is specialized for IO exceptions.
+-- This simplifies usage as no explicit type signatures are necessary.
+--
+-- Since 0.5.6
+tryIO :: MonadBaseControl IO m => m a -> m (Either IOException a)
+tryIO = try
+
+-- |
+--
+-- Since 0.5.6
+asSomeException :: SomeException -> SomeException
+asSomeException = id
+
+-- |
+--
+-- Since 0.5.6
+asIOException :: IOException -> IOException
+asIOException = id
diff --git a/ClassyPrelude/ByteString.hs b/ClassyPrelude/ByteString.hs
--- a/ClassyPrelude/ByteString.hs
+++ b/ClassyPrelude/ByteString.hs
@@ -107,3 +107,5 @@
 
 instance CanUnzip ByteString Word8 ByteString Word8 [] where
     unzip = ByteString.unzip
+
+instance CanEmpty ByteString
diff --git a/ClassyPrelude/Classes.hs b/ClassyPrelude/Classes.hs
--- a/ClassyPrelude/Classes.hs
+++ b/ClassyPrelude/Classes.hs
@@ -268,3 +268,8 @@
 
 class CanUnzip7 c1 i1 c2 i2 c3 i3 c4 i4 c5 i5 c6 i6 c7 i7 t | c1 -> i1, c2 -> i2, c3 -> i3, c4 -> i4, c5 -> i5, c6 -> i6, c7 -> i7 where
     unzip7 :: t (i1, i2, i3, i4, i5, i6, i7) -> (c1, c2, c3, c4, c5, c6, c7)
+
+class CanEmpty a where
+  empty :: a
+  default empty :: Monoid a => a
+  empty = mempty
diff --git a/ClassyPrelude/FilePath.hs b/ClassyPrelude/FilePath.hs
--- a/ClassyPrelude/FilePath.hs
+++ b/ClassyPrelude/FilePath.hs
@@ -23,3 +23,5 @@
         case stripPrefix a b of
             Nothing -> False
             Just {} -> True
+
+instance CanEmpty FilePath
diff --git a/ClassyPrelude/HashMap.hs b/ClassyPrelude/HashMap.hs
--- a/ClassyPrelude/HashMap.hs
+++ b/ClassyPrelude/HashMap.hs
@@ -57,3 +57,6 @@
 
 instance (Hashable k, Eq k) => CanIntersection (HashMap k a) where
     intersection = HashMap.intersection
+
+instance (Hashable k, Eq k) => CanEmpty (HashMap k a) where
+    empty = HashMap.empty
diff --git a/ClassyPrelude/HashSet.hs b/ClassyPrelude/HashSet.hs
--- a/ClassyPrelude/HashSet.hs
+++ b/ClassyPrelude/HashSet.hs
@@ -48,3 +48,6 @@
 
 instance (Eq a, Hashable a) => CanIntersection (HashSet a) where
     intersection = HashSet.intersection
+
+instance (Eq a, Hashable a) => CanEmpty (HashSet a) where
+    empty = HashSet.empty
diff --git a/ClassyPrelude/LByteString.hs b/ClassyPrelude/LByteString.hs
--- a/ClassyPrelude/LByteString.hs
+++ b/ClassyPrelude/LByteString.hs
@@ -113,3 +113,5 @@
 
 instance CanUnzip LByteString Word8 LByteString Word8 [] where
     unzip = LByteString.unzip
+
+instance CanEmpty LByteString
diff --git a/ClassyPrelude/LText.hs b/ClassyPrelude/LText.hs
--- a/ClassyPrelude/LText.hs
+++ b/ClassyPrelude/LText.hs
@@ -137,3 +137,5 @@
 
 instance CanZip LText Char LText Char [] where
     zip = LText.zip
+
+instance CanEmpty LText
diff --git a/ClassyPrelude/List.hs b/ClassyPrelude/List.hs
--- a/ClassyPrelude/List.hs
+++ b/ClassyPrelude/List.hs
@@ -211,3 +211,6 @@
 
 instance CanUnzip7 ([] a) a ([] b) b ([] c) c ([] d) d ([] e) e ([] f) f ([] g) g [] where
     unzip7 = List.unzip7
+
+instance CanEmpty [a] where
+    empty = []
diff --git a/ClassyPrelude/Map.hs b/ClassyPrelude/Map.hs
--- a/ClassyPrelude/Map.hs
+++ b/ClassyPrelude/Map.hs
@@ -57,3 +57,6 @@
 
 instance (Ord k) => CanIntersection (Map k a) where
     intersection = Map.intersection
+
+instance (Ord k) => CanEmpty (Map k a) where
+    empty = Map.empty
diff --git a/ClassyPrelude/Maybe.hs b/ClassyPrelude/Maybe.hs
--- a/ClassyPrelude/Maybe.hs
+++ b/ClassyPrelude/Maybe.hs
@@ -58,3 +58,6 @@
 
 instance CanFind (Maybe a) a where
   find = Foldable.find
+
+instance CanEmpty (Maybe a) where
+  empty = Nothing
diff --git a/ClassyPrelude/Sequence.hs b/ClassyPrelude/Sequence.hs
--- a/ClassyPrelude/Sequence.hs
+++ b/ClassyPrelude/Sequence.hs
@@ -151,3 +151,6 @@
 
 instance CanZip4 (Seq a) a (Seq b) b (Seq c) c (Seq d) d Seq where
     zip4 = Seq.zip4
+
+instance CanEmpty (Seq a) where
+    empty = Seq.empty
diff --git a/ClassyPrelude/Set.hs b/ClassyPrelude/Set.hs
--- a/ClassyPrelude/Set.hs
+++ b/ClassyPrelude/Set.hs
@@ -64,3 +64,6 @@
 
 instance (Ord a) => CanIntersection (Set a) where
     intersection = Set.intersection
+
+instance (Ord a) => CanEmpty (Set a) where
+    empty = Set.empty
diff --git a/ClassyPrelude/Text.hs b/ClassyPrelude/Text.hs
--- a/ClassyPrelude/Text.hs
+++ b/ClassyPrelude/Text.hs
@@ -129,3 +129,5 @@
 
 instance CanZip Text Char Text Char [] where
     zip = Text.zip
+
+instance CanEmpty Text
diff --git a/ClassyPrelude/Vector.hs b/ClassyPrelude/Vector.hs
--- a/ClassyPrelude/Vector.hs
+++ b/ClassyPrelude/Vector.hs
@@ -182,3 +182,6 @@
 
 instance CanUnzip6 (Vector a) a (Vector b) b (Vector c) c (Vector d) d (Vector e) e (Vector f) f Vector where
     unzip6 = Vector.unzip6
+
+instance CanEmpty (Vector a) where
+    empty = Vector.empty
diff --git a/classy-prelude.cabal b/classy-prelude.cabal
--- a/classy-prelude.cabal
+++ b/classy-prelude.cabal
@@ -1,5 +1,5 @@
 name:                classy-prelude
-version:             0.5.4
+version:             0.5.6
 synopsis:            A typeclass-based Prelude.
 description:         Focuses on using common typeclasses when possible, and creating new ones to avoid name clashing. Exposes many recommended datastructures (Map, ByteString, etc) directly without requiring long import lists and qualified modules.
 homepage:            https://github.com/snoyberg/classy-prelude
@@ -39,6 +39,7 @@
                      , unordered-containers
                      , hashable
                      , lifted-base                   >= 0.2
+                     , monad-control
   ghc-options:         -Wall -fno-warn-orphans
 
 test-suite test
diff --git a/test/main.hs b/test/main.hs
--- a/test/main.hs
+++ b/test/main.hs
@@ -8,7 +8,7 @@
 import ClassyPrelude
 import ClassyPrelude.Classes
 import Test.QuickCheck.Arbitrary
-import Prelude (asTypeOf, undefined, fromIntegral)
+import Prelude (asTypeOf, fromIntegral)
 import qualified Prelude
 import Control.Monad.Trans.Writer (tell, Writer, runWriter)
 import Data.Maybe (isJust)
@@ -17,6 +17,7 @@
 dictionaryProps
     :: ( CanInsertVal a Int Char
        , CanDeleteVal a Int
+       , CanEmpty a
        , Show a
        , Eq a
        , Arbitrary a
@@ -112,6 +113,7 @@
                , Arbitrary a
                , CanPack a i
                , CanLength a len
+               , CanEmpty a
                , Prelude.Num len
                , Eq len
                , CanNull a
