diff --git a/COPYING b/COPYING
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-Copyright (c) 2012, 2013, 2014 Joachim Fasting
+Copyright (c) 2012, 2013, 2014, 2016 Joachim Fasting
 
 All rights reserved.
 
diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+acme-omitted 3.0.0.0, 2016-08-19
+	* Factor out Acme.OmittedOrUndefined
 acme-omitted 2.0.0.0, 2014-10-20
 	* Factor out Acme.Undefined
 acme-omitted 1.2.0.0, 2013-10-13
diff --git a/acme-omitted.cabal b/acme-omitted.cabal
--- a/acme-omitted.cabal
+++ b/acme-omitted.cabal
@@ -1,5 +1,5 @@
 Name:                acme-omitted
-Version:             2.0.0.0
+Version:             3.0.0.0
 Synopsis:            A name for omitted definitions
 Category:            Acme
 Stability:           stable
@@ -14,7 +14,7 @@
 
 Author:              Joachim Fasting
 Maintainer:          joachifm@fastmail.fm
-Copyright:           (c) 2013-2014 Joachim Fasting
+Copyright:           (c) 2013-2016 Joachim Fasting
 Homepage:            https://github.com/joachifm/acme-omitted#readme
 
 Extra-source-files:
@@ -24,6 +24,15 @@
 Build-type:          Simple
 Cabal-version:       >= 1.10
 
+Tested-With:
+            GHC == 7.0.4
+          , GHC == 7.2.2
+          , GHC == 7.4.2
+          , GHC == 7.6.3
+          , GHC == 7.8.4
+          , GHC == 7.10.3
+          , GHC == 8.0.1
+
 Source-repository head
   Type: git
   location: https://github.com/joachifm/acme-omitted.git
@@ -32,7 +41,10 @@
   Default-language: Haskell2010
 
   Exposed-modules:     Acme.Omitted,
-                       Acme.Undefined
+                       Acme.Undefined,
+                       Acme.OmittedOrUndefined
+
+  Other-modules:       Acme.OmittedOrUndefined.Internal
 
   Build-depends:
     base >=3 && <5
diff --git a/src/Acme/Omitted.hs b/src/Acme/Omitted.hs
--- a/src/Acme/Omitted.hs
+++ b/src/Acme/Omitted.hs
@@ -1,16 +1,12 @@
 {-|
 Module      : Acme.Omitted
 Description : A name for omitted definitions
-Copyright   : (c) 2013-2014 Joachim Fasting
+Copyright   : (c) 2013-2016 Joachim Fasting
 License     : BSD3
 
 Maintainer  : joachifm@fastmail.fm
 Stability   : stable
 Portability : portable
-
-This module provides the means to indicate that a definition
-has been omitted (for whatever reason), as opposed to being
-inherently undefinable.
 -}
 
 module Acme.Omitted
@@ -20,13 +16,15 @@
 
   ) where
 
--- | Alternative syntax for 'omitted' that has been carefully
--- optimised for programmer convenience and visual presentation
--- (e.g., for use in printed documents).
---
--- Example usage:
---
---    > definition = (...)
+{-|
+Alternative syntax for 'omitted' that has been carefully optimised for
+programmer convenience and visual presentation (e.g., for use in printed
+documents).
+
+Example usage:
+
+  > definition = (...)
+-}
 (...) :: a
 (...) = omitted
 
diff --git a/src/Acme/OmittedOrUndefined.hs b/src/Acme/OmittedOrUndefined.hs
new file mode 100644
--- /dev/null
+++ b/src/Acme/OmittedOrUndefined.hs
@@ -0,0 +1,92 @@
+{-|
+Module      : Acme.OmittedOrUndefined
+Description : Is it truly undefined or merely omitted?
+Copyright   : (c) 2013-2016 Joachim Fasting
+License     : BSD3
+
+Maintainer  : joachifm@fastmail.fm
+Stability   : provisional
+Portability : portable
+-}
+
+module Acme.OmittedOrUndefined (
+    -- * Usage
+    -- $usage
+
+    -- * Observing the difference between \"omitted\" and \"undefined\"
+    --
+    -- $observing
+    isOmitted
+  , isUndefined
+  , isPreludeUndefined
+) where
+
+import Acme.OmittedOrUndefined.Internal
+
+{-$usage
+@
+module AwesomeSauce where
+
+import Prelude hiding (undefined)
+import Acme.Omitted
+import Acme.Undefined
+
+tooLazyToDefine     = (...)
+
+actuallyUndefinable = undefined
+
+main = do
+  merelyOmitted <- 'isOmitted' tooLazyToDefine
+  putStrLn \"Definition was merely omitted\"
+  (...)
+  trulyUndefined <- 'isUndefined' actuallyUndefinable
+  putStrLn \"Definition is truly undefinable\"
+@
+-}
+
+{-$observing
+
+Consistent use of 'undefined' and 'omitted' can clarify the intent of the
+programmer, but there is no way to statically prevent incorrect uses of
+'undefined' (e.g., due to ignorance).
+Consequently, 'isUndefined' will return bogus results every now and then,
+which is why it is modelled as an 'IO' action and not a pure function.
+
+Nevertheless, the user can identify incorrect uses of 'undefined' more
+easily than before.
+To wit, if
+
+@
+isUndefined twoPlusTwo = return True
+@
+
+then, surely, something is amiss.
+
+For backwards-compatibility, we also support detecting the standard
+implementation of undefined, about which we cannot infer anything except
+that its evaluation will terminate with no useful result.
+-}
+
+-- | Answer the age-old question \"was this definition omitted?\"
+--
+-- @
+-- isOmitted 0           = return False
+-- isOmitted 'undefined' = return False
+-- isOmitted 'omitted'   = return True
+-- @
+isOmitted :: a -> IO Bool
+isOmitted = isErrorCall "Acme.Omitted.omitted"
+
+-- | ... or is it really 'undefined'?
+--
+-- @
+-- isUndefined 0           = return False
+-- isUndefined 'undefined' = return True
+-- isUndefined 'omitted'   = return False
+-- @
+isUndefined :: a -> IO Bool
+isUndefined = isErrorCall "Acme.Undefined.undefined"
+
+-- | A version of 'isUndefined' for \"Prelude.undefined\".
+isPreludeUndefined :: a -> IO Bool
+isPreludeUndefined = isErrorCall "Prelude.undefined"
diff --git a/src/Acme/OmittedOrUndefined/Internal.hs b/src/Acme/OmittedOrUndefined/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Acme/OmittedOrUndefined/Internal.hs
@@ -0,0 +1,18 @@
+{-|
+Module      : Acme.OmittedOrUndefined.Internal
+Description : Internal module
+Copyright   : (c) 2016 Joachim Fasting
+License     : BSD3
+
+Maintainer  : joachifm@fastmail.fm
+Stability   : stable
+Portability : portable
+-}
+
+module Acme.OmittedOrUndefined.Internal where
+
+import qualified Control.Exception as E
+
+isErrorCall :: String -> a -> IO Bool
+isErrorCall s x = (E.evaluate x >> return False)
+                  `E.catch` (\(E.ErrorCall e) -> return $ e == s)
diff --git a/src/Acme/Undefined.hs b/src/Acme/Undefined.hs
--- a/src/Acme/Undefined.hs
+++ b/src/Acme/Undefined.hs
@@ -1,128 +1,23 @@
 {-|
 Module      : Acme.Undefined
 Description : Undefined redefined
-Copyright   : (c) 2013-2014 Joachim Fasting
+Copyright   : (c) 2013-2016 Joachim Fasting
 License     : BSD3
 
 Maintainer  : joachifm@fastmail.fm
 Stability   : stable
 Portability : portable
-
-This module provides an alternative implementation of
-\"Prelude.undefined\", intended exclusively for denoting
-truly undefinable values.
 -}
 
 module Acme.Undefined (
-    -- * Usage
-    -- $usage
-  
-    -- * \"Undefined\" redefined
-    --
-    -- $undefined
     undefined
-
-    -- * Observing the difference between \"omitted\" and \"undefined\"
-    --
-    -- $observing
-  , isOmitted
-  , isUndefined
-  , isPreludeUndefined
   ) where
 
 import Prelude hiding (undefined)
-import qualified Control.Exception as E
 
-{-$usage
-@
-module AwesomeSauce where
-
-import Prelude hiding (undefined)
-import Acme.Omitted
-import Acme.Undefined
-
-tooLazyToDefine     = (...)
-
-actuallyUndefinable = undefined
-
-main = do
-  merelyOmitted <- 'isOmitted' tooLazyToDefine
-  putStrLn \"Definition was merely omitted\"
-  (...)
-  trulyUndefined <- 'isUndefined' actuallyUndefinable
-  putStrLn \"Definition is truly undefinable\"
-@
--}
-
-{-$undefined
-
-Lacking a dedicated name for omitted defintions, users of Standard
-Haskell are left with no choice but to use \"undefined\" for both
-the undefinable and the omitted.
-This makes the standard implementation of \"undefined\" deficient, we
-cannot be sure what the programmer has intended, only that the definition is
-missing.
-The following implementation of undefined is similar in every way to
-the standard implementation, but is free from conceptual contamination.
+{-|
+Denotes all values that are, fundamentally, undefinable.  The contract of
+'undefined' is that it will never be used for merely omitted definitions.
 -}
-
--- | Denotes all values that are, fundamentally, undefinable.
---
--- The contract of 'undefined' is that it will never be used for
--- merely omitted definitions.
 undefined :: a
 undefined = error "Acme.Undefined.undefined"
-
-{-$observing
-
-Consistent use of 'undefined' and 'omitted' can clarify the intent of the
-programmer, but there is still no way to statically prevent incorrect
-uses of 'undefined' (e.g., due to ignorance).
-Consequently, 'isUndefined' will return bogus results every now and then,
-which is why it is modelled as an 'IO' action and not a pure function.
-
-Nevertheless, the user can identify incorrect uses of 'undefined' more easily
-than before.
-To wit, if
-
-@
-isUndefined twoPlusTwo = return True
-@
-
-then, surely, something is amiss.
-We know that the programmer has made the mistake of believing @2+2@ to be undefined,
-that she has not simply run out of time or gotten an important phone call while
-writing down the solution.
-
-For backwards-compatibility, we also support detecting the standard
-implementation of undefined, about which we cannot infer anything except
-that its evaluation will terminate with no useful result.
--}
-
--- | Answer the age-old question \"was this definition omitted?\"
---
--- @
--- isOmitted 0           = return False
--- isOmitted 'undefined' = return False
--- isOmitted 'omitted'   = return True
--- @
-isOmitted :: a -> IO Bool
-isOmitted = isErrorCall "Acme.Omitted.omitted"
-
--- | ... or is it really 'undefined'?
---
--- @
--- isUndefined 0           = return False
--- isUndefined 'undefined' = return True
--- isUndefined 'omitted'   = return False
--- @
-isUndefined :: a -> IO Bool
-isUndefined = isErrorCall "Acme.Undefined.undefined"
-
--- | A version of 'isUndefined' for \"Prelude.undefined\".
-isPreludeUndefined :: a -> IO Bool
-isPreludeUndefined = isErrorCall "Prelude.undefined"
-
-isErrorCall :: String -> a -> IO Bool
-isErrorCall s x = (E.evaluate x >> return False)
-                  `E.catch` (\(E.ErrorCall e) -> return $ e == s)
