diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,6 +2,8 @@
 [Extensible Effects: An Alternative to Monad Transformers](http://okmij.org/ftp/Haskell/extensible/).
 Please read the [paper](http://okmij.org/ftp/Haskell/extensible/exteff.pdf) for details.
 
+[![Build Status](https://travis-ci.org/bfops/extensible-effects.svg?branch=master)](https://travis-ci.org/bfops/extensible-effects)
+
 ## Advantages
 
   * Effects can be added, removed, and interwoven without changes to code not
diff --git a/extensible-effects.cabal b/extensible-effects.cabal
--- a/extensible-effects.cabal
+++ b/extensible-effects.cabal
@@ -6,7 +6,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             1.7.2.1
+version:             1.8.0.0
 
 -- A short (one-line) description of the package.
 synopsis:            An Alternative to Monad Transformers
@@ -72,7 +72,7 @@
                        Control.Eff.Writer.Lazy
                        Control.Eff.Writer.Strict
                        Control.Eff.Trace
-                       Data.OpenUnion1
+                       Data.OpenUnion
 
   -- Modules included in this library but not exported.
   other-modules:       Data.OpenUnion.Internal.Base
diff --git a/src/Control/Eff.hs b/src/Control/Eff.hs
--- a/src/Control/Eff.hs
+++ b/src/Control/Eff.hs
@@ -83,7 +83,7 @@
 
 import Control.Applicative (Applicative (..), (<$>))
 import Control.Monad (ap)
-import Data.OpenUnion1
+import Data.OpenUnion
 import Data.Typeable
 
 #if MIN_VERSION_base(4,7,0)
diff --git a/src/Data/OpenUnion.hs b/src/Data/OpenUnion.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/OpenUnion.hs
@@ -0,0 +1,101 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE CPP #-}
+
+-- Only for SetMember below, when emulating Monad Transformers
+{-# LANGUAGE FunctionalDependencies, UndecidableInstances #-}
+
+#if MIN_VERSION_base(4,7,0)
+#define Typeable1 Typeable
+#endif
+-- | Original work at <http://okmij.org/ftp/Haskell/extensible/OpenUnion1.hs>
+-- and <http://okmij.org/ftp/Haskell/extensible/OpenUnion2.hs>.
+-- Open unions (type-indexed co-products) for extensible effects.
+--
+-- TODO: see if we can do away with Typeable constraints, perhaps by
+-- incorporating ideas from <http://okmij.org/ftp/Haskell/extensible/TList.hs>
+module Data.OpenUnion(
+  -- * Classes
+  Member
+  -- ** Monad transformer related
+  , SetMember
+    -- * Type-indexed co-product
+    -- ** Datatypes
+  , Union
+  , (:>)
+    -- ** Functions
+  , inj
+  , prj
+  , prjForce
+  , decomp
+  , unsafeReUnion
+  , weaken
+  ) where
+
+import Control.Applicative ((<$>))
+import Data.Typeable
+#if __GLASGOW_HASKELL__ >= 781
+import Data.OpenUnion.Internal.OpenUnion2
+#else
+import Data.OpenUnion.Internal.OpenUnion1
+#endif
+
+infixl 4 <?>
+
+-- | infix form of `fromMaybe`.
+(<?>) :: Maybe a -> a -> a
+Just a <?> _ = a
+_ <?> a = a
+
+-- | for the sake of @gcast1@ used below in @`prj`@
+newtype Id a = Id { runId :: a }
+  deriving Typeable
+
+-- | `SetMember` is similar to `Member`, but it allows types to belong to a
+-- \"set\". For every set, only one member can be in @r@ at any given time.
+-- This allows us to specify exclusivity and uniqueness among arbitrary effects:
+--
+-- > -- Terminal effects (effects which must be run last)
+-- > data Terminal
+-- >
+-- > -- Make Lifts part of the Terminal effects set.
+-- > -- The fundep assures that there can only be one Terminal effect for any r.
+-- > instance Member (Lift m) r => SetMember Terminal (Lift m) r
+-- >
+-- > -- Only allow a single unique Lift effect, by making a "Lift" set.
+-- > instance Member (Lift m) r => SetMember Lift (Lift m) r
+class (Member t r) => SetMember set (t :: * -> *) r | r set -> t
+instance (MemberU set t r) => SetMember set t r
+
+{-# INLINE inj #-}
+-- | Construct a Union.
+inj :: (Functor t, Typeable1 t, Member t r) => t v -> Union r v
+inj = Union
+
+{-# INLINE prj #-}
+-- | Try extracting the contents of a Union as a given type.
+prj :: (Typeable1 t, Member t r) => Union r v -> Maybe (t v)
+prj (Union v) = runId <$> gcast1 (Id v)
+
+{-# INLINE prjForce #-}
+-- | Extract the contents of a Union as a given type.
+-- If the Union isn't of that type, a runtime error occurs.
+prjForce :: (Typeable1 t, Member t r) => Union r v -> (t v -> a) -> a
+prjForce u f = f <$> prj u <?> error "prjForce with an invalid type"
+
+{-# INLINE decomp #-}
+-- | Try extracting the contents of a Union as a given type.
+-- If we can't, return a reduced Union that excludes the type we just checked.
+decomp :: Typeable1 t => Union (t :> r) v -> Either (Union r v) (t v)
+decomp u = Right <$> prj u <?> Left (unsafeReUnion u)
+
+{-# INLINE weaken #-}
+weaken :: (Typeable1 t, Functor t) => Union r w -> Union (t :> r) w
+weaken (Union x) = Union x
+
+{-# INLINE unsafeReUnion #-}
+-- | Juggle types for a Union. Use cautiously.
+unsafeReUnion :: Union r w -> Union t w
+unsafeReUnion (Union v) = Union v
diff --git a/src/Data/OpenUnion/Internal/Base.hs b/src/Data/OpenUnion/Internal/Base.hs
--- a/src/Data/OpenUnion/Internal/Base.hs
+++ b/src/Data/OpenUnion/Internal/Base.hs
@@ -19,6 +19,9 @@
 -- Where @r@ is @t1 :> t2 ... :> tn@, @`Union` r v@ can be constructed with a
 -- value of type @ti v@.
 -- Ideally, we should be able to add the constraint @`Member` t r@.
+--
+-- NOTE: exposing the constructor below allows users to bypass the type
+-- system. See 'Data.OpenUnion.unsafeReUnion' for example.
 data Union r v = forall t. (Functor t, Typeable1 t) => Union (t v)
 
 instance Functor (Union r) where
diff --git a/src/Data/OpenUnion1.hs b/src/Data/OpenUnion1.hs
deleted file mode 100644
--- a/src/Data/OpenUnion1.hs
+++ /dev/null
@@ -1,95 +0,0 @@
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE CPP #-}
-
--- Only for SetMember below, when emulating Monad Transformers
-{-# LANGUAGE FunctionalDependencies, UndecidableInstances #-}
-
-#if MIN_VERSION_base(4,7,0)
-#define Typeable1 Typeable
-#endif
--- | Original work at <http://okmij.org/ftp/Haskell/extensible/OpenUnion1.hs>.
--- Open unions (type-indexed co-products) for extensible effects.
--- This implementation relies on _closed_ overlapping instances
--- (or closed type function overlapping soon to be added to GHC).
---
--- TODO: re-evaluate <https://github.com/bfops/extensible-effects/issues/13>
-module Data.OpenUnion1( Union (..)
-                      , Member
-                      , SetMember
-                      , (:>)
-                      , inj
-                      , prj
-                      , prjForce
-                      , decomp
-                      , unsafeReUnion
-                      , weaken
-                      ) where
-
-import Control.Applicative ((<$>))
-import Data.Typeable
-#if __GLASGOW_HASKELL__ >= 781
-import Data.OpenUnion.Internal.OpenUnion2
-#else
-import Data.OpenUnion.Internal.OpenUnion1
-#endif
-
-infixl 4 <?>
-
--- | infix form of `fromMaybe`.
-(<?>) :: Maybe a -> a -> a
-Just a <?> _ = a
-_ <?> a = a
-
--- | for the sake of @gcast1@ used below in @`prj`@
-newtype Id a = Id { runId :: a }
-  deriving Typeable
-
--- | `SetMember` is similar to `Member`, but it allows types to belong to a
--- \"set\". For every set, only one member can be in @r@ at any given time.
--- This allows us to specify exclusivity and uniqueness among arbitrary effects:
---
--- > -- Terminal effects (effects which must be run last)
--- > data Terminal
--- >
--- > -- Make Lifts part of the Terminal effects set.
--- > -- The fundep assures that there can only be one Terminal effect for any r.
--- > instance Member (Lift m) r => SetMember Terminal (Lift m) r
--- >
--- > -- Only allow a single unique Lift effect, by making a "Lift" set.
--- > instance Member (Lift m) r => SetMember Lift (Lift m) r
-class (Member t r) => SetMember set (t :: * -> *) r | r set -> t
-instance (MemberU set t r) => SetMember set t r
-
-{-# INLINE inj #-}
--- | Construct a Union.
-inj :: (Functor t, Typeable1 t, Member t r) => t v -> Union r v
-inj = Union
-
-{-# INLINE prj #-}
--- | Try extracting the contents of a Union as a given type.
-prj :: (Typeable1 t, Member t r) => Union r v -> Maybe (t v)
-prj (Union v) = runId <$> gcast1 (Id v)
-
-{-# INLINE prjForce #-}
--- | Extract the contents of a Union as a given type.
--- If the Union isn't of that type, a runtime error occurs.
-prjForce :: (Typeable1 t, Member t r) => Union r v -> (t v -> a) -> a
-prjForce u f = f <$> prj u <?> error "prjForce with an invalid type"
-
-{-# INLINE decomp #-}
--- | Try extracting the contents of a Union as a given type.
--- If we can't, return a reduced Union that excludes the type we just checked.
-decomp :: Typeable1 t => Union (t :> r) v -> Either (Union r v) (t v)
-decomp u = Right <$> prj u <?> Left (unsafeReUnion u)
-
-{-# INLINE weaken #-}
-weaken :: (Typeable1 t, Functor t) => Union r w -> Union (t :> r) w
-weaken (Union x) = Union x
-
-{-# INLINE unsafeReUnion #-}
--- | Juggle types for a Union. Use cautiously.
-unsafeReUnion :: Union r w -> Union t w
-unsafeReUnion (Union v) = Union v
