diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for Empty
+
+## 0.1.0.0  -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/Empty.cabal b/Empty.cabal
new file mode 100644
--- /dev/null
+++ b/Empty.cabal
@@ -0,0 +1,25 @@
+-- Initial Empty.cabal generated by cabal init.  For further documentation,
+--  see http://haskell.org/cabal/users-guide/
+
+name:                Empty
+version:             0.1.0.0
+synopsis:            A type class for empty containers
+description:         HasEmpty f has a member empty of type forall a. f a
+license:             BSD3
+license-file:        LICENSE
+author:              Isaac Shapira
+maintainer:          fresheyeball@gmail.com
+-- copyright:
+category:            Control
+build-type:          Simple
+extra-source-files:  ChangeLog.md
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Control.Empty
+  -- other-modules:
+  -- other-extensions:
+  build-depends:       base >=4.9 && <4.10
+                     , containers
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2017, Isaac Shapira
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Isaac Shapira nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/src/Control/Empty.hs b/src/Control/Empty.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Empty.hs
@@ -0,0 +1,88 @@
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE RankNTypes        #-}
+{-# LANGUAGE TypeOperators     #-}
+
+module Control.Empty where
+
+import qualified Control.Applicative             as AP
+import           Data.Functor.Compose
+import qualified Data.Functor.Product            as FP
+import qualified Data.IntMap                     as IntMap
+import qualified Data.Map                        as Map
+import           Data.Proxy
+import           Data.Semigroup
+import qualified Data.Sequence                   as Seq
+import qualified Data.Set                        as Set
+import           GHC.Conc
+import           Text.ParserCombinators.ReadP
+import           Text.ParserCombinators.ReadPrec
+
+{-| The class of type of @* -> *@ which may be empty.
+    There is only one law for HasEmpty and its enforced by the type.
+    The law is that there exists a value in type f for which a is fully generic.
+    This alone is often enough to uniquely determine the value for a given,
+    data type.
+
+    Additional laws for HasEmpty work backwards, @empty@ has a relationships
+    with other classes. So if @f@ is a member of one of these classes,
+    the following should hold.
+
+    [/Functor identity/]
+
+        @g \<$\> empty = empty@
+
+    [/Applicative annililation left/]
+
+        @x \<*\> empty = empty@
+
+    [/Applicative annililation right/]
+
+        @empty \<*\> x = empty@
+
+    [/Monad identity/]
+
+        @empty >>= f = empty@
+
+    [/Alternative empty/]
+
+        @empty = Alternative.empty@
+
+    [/MonadPlus mzero/]
+
+        @empty = mzero@
+
+    [/Foldable identity/]
+
+        @foldr f x empty = empty@
+
+-}
+class HasEmpty f where
+    empty :: forall a. f a
+    default empty :: AP.Alternative f => f a
+    empty = AP.empty
+
+instance HasEmpty Maybe
+instance HasEmpty []
+instance HasEmpty IO
+instance HasEmpty STM
+instance HasEmpty Proxy
+instance HasEmpty Option
+instance HasEmpty ReadP
+instance HasEmpty ReadPrec
+
+instance (AP.Alternative f, AP.Alternative g) => HasEmpty (FP.Product f g)
+instance (AP.Alternative f, AP.Applicative g) => HasEmpty (Compose f g)
+
+instance HasEmpty IntMap.IntMap where empty = mempty
+instance HasEmpty (Map.Map k)   where empty = Map.empty
+instance HasEmpty Seq.Seq       where empty = Seq.empty
+instance HasEmpty Set.Set       where empty = Set.empty
+
+
+coerce :: HasEmpty f => a -> f b
+coerce _ = empty
+
+
+isEmpty :: (HasEmpty f, Eq (f a)) => f a -> Bool
+isEmpty = (== empty)
