diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Dai (c) 2017
+
+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 Author name here 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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# data-constructors
+See [Haddocks](http://daig.github.io/data-constructors) for the latest tagged version
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/bench/Bench.hs b/bench/Bench.hs
new file mode 100644
--- /dev/null
+++ b/bench/Bench.hs
@@ -0,0 +1,38 @@
+{-# language TemplateHaskell #-}
+{-# language TypeApplications #-}
+{-# language DeriveAnyClass #-}
+{-# language DeriveDataTypeable #-}
+{-# language DeriveGeneric #-}
+module Main where
+import Data.Constructors.TH
+import Data.Function (on)
+import Data.Data (Data,toConstr)
+import GHC.Generics (Generic)
+import Criterion
+import Criterion.Main (defaultMain)
+import Test.QuickCheck (Arbitrary(..),generate,vectorOf)
+import Test.QuickCheck.Gen (Gen,oneof)
+import Control.DeepSeq
+
+data PhpValue = VoidValue | IntValue Integer | BoolValue Bool
+  deriving (Generic,Data,Show,NFData)
+$(deriveEqC ''PhpValue)
+instance Arbitrary PhpValue where
+  arbitrary = oneof [pure VoidValue, IntValue <$> arbitrary, BoolValue <$> arbitrary]
+
+eqConstrDefault :: Data a => a -> a -> Bool
+eqConstrDefault = (==) `on` toConstr
+
+prop_EqC :: PhpValue -> PhpValue -> Bool
+prop_EqC x y = eqConstrDefault x y == eqConstr x y
+
+main = defaultMain [
+  env setupEnv $ \ e ->
+    bgroup "EqC"
+      [bench "TH" $ whnf (\(a,b) -> eqConstr a b) e
+      ,bench "Data" $ whnf (\(a,b) -> eqConstrDefault a b) e
+      ]
+  ]
+  where
+    setupEnv :: IO (PhpValue,PhpValue)
+    setupEnv = generate $ (,) <$> arbitrary <*> arbitrary
diff --git a/data-constructors.cabal b/data-constructors.cabal
new file mode 100644
--- /dev/null
+++ b/data-constructors.cabal
@@ -0,0 +1,39 @@
+name:                data-constructors
+version:             0.1.0.0
+synopsis:            Generically compare data by their constructors
+description:         Utilities for comparing data constructor tags, and TH functions for generating comparison definitions
+homepage:            https://github.com/daig/data-constructors#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Dai
+maintainer:          daig@sodality.cc
+copyright:           2017 Dai
+category:            Data
+build-type:          Simple
+extra-source-files:  README.md
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Data.Constructors.EqC, Data.Constructors.TH
+  build-depends:       base >= 4.7 && < 5
+                      ,template-haskell
+  default-language:    Haskell2010
+  ghc-options:         -Wall
+  default-extensions: LambdaCase
+test-suite data-constructors-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  build-depends:       base , data-constructors, QuickCheck
+  default-language:    Haskell2010
+benchmark bench-EqC
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      bench
+  main-is:             Bench.hs
+  build-depends:       base,data-constructors,QuickCheck,criterion,deepseq
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/daig/data-constructors
diff --git a/src/Data/Constructors/EqC.hs b/src/Data/Constructors/EqC.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Constructors/EqC.hs
@@ -0,0 +1,11 @@
+{-# language DefaultSignatures #-}
+module Data.Constructors.EqC (EqC(..)) where
+import Data.Function (on)
+import Data.Data (Data,toConstr)
+
+class EqC a where
+  -- | Compare the outermost constructor for a datatype.
+  -- Instances should satisfy @eqConstr (C a) (K b) = True@ iff C=K
+  eqConstr :: a -> a -> Bool
+  default eqConstr :: Data a => a -> a -> Bool
+  eqConstr = on (==) toConstr
diff --git a/src/Data/Constructors/TH.hs b/src/Data/Constructors/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Constructors/TH.hs
@@ -0,0 +1,43 @@
+{-# LANGUAGE TemplateHaskell #-}
+module Data.Constructors.TH (EqC(..),deriveEqC) where
+import Data.Constructors.EqC
+
+import Language.Haskell.TH as TH 
+import Language.Haskell.TH.Syntax as TH
+
+-- | Derive an instance of @EqC@ for any simple type
+-- For example, @deriveEqC ''Either@ will generate:
+--
+-- > instance EqC (Either a b) where
+-- >   eqConstr Left{}  Left{}  = True
+-- >   eqConstr Right{} Right{} = True
+-- >   eqConstr _       _       = False
+deriveEqC :: Name -> DecsQ
+deriveEqC n = do
+  (saturatedType,constructors) <- extractTypeCons n
+  return $ 
+    [InstanceD
+      Nothing
+      []
+      (AppT (ConT ''EqC) saturatedType)
+      [FunD 'eqConstr constructors]]
+
+extractTypeCons :: Name -> Q (TH.Type,[Clause])
+extractTypeCons n = do
+  true <- lift True
+  false <- lift False
+  reify n <&> \case
+    TyConI (DataD _ _ tyVars _ cons _) ->
+        (foldl (\c -> AppT c . extractTV) (ConT n) tyVars
+        ,foldr (\c acc -> Clause [RecP c [], RecP c []] (NormalB true) [] : acc)
+               [Clause [WildP,WildP] (NormalB false) []]
+               (map (\(NormalC n' _) -> n') cons))
+    _ -> error "invalid name"
+
+extractTV :: TyVarBndr -> TH.Type
+extractTV = \case
+  PlainTV n -> VarT n
+  KindedTV n _ -> VarT n
+
+(<&>) :: Functor f => f a -> (a -> b) -> f b
+(<&>) = flip (<$>)
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,22 @@
+{-# language TemplateHaskell #-}
+{-# language DeriveDataTypeable #-}
+{-# language DeriveGeneric #-}
+module Main where
+import Data.Constructors.TH
+import Data.Function (on)
+import Data.Data (Data,toConstr)
+import Test.QuickCheck (Arbitrary(..),sample,quickCheck)
+import Test.QuickCheck.Gen (Gen,oneof)
+
+data PhpValue = VoidValue | IntValue Integer | BoolValue Bool deriving (Data,Show)
+$(deriveEqC ''PhpValue)
+instance Arbitrary PhpValue where
+  arbitrary = oneof [pure VoidValue, IntValue <$> arbitrary, BoolValue <$> arbitrary]
+
+eqConstrDefault :: Data a => a -> a -> Bool
+eqConstrDefault = (==) `on` toConstr
+
+prop_EqC :: PhpValue -> PhpValue -> Bool
+prop_EqC x y = eqConstrDefault x y == eqConstr x y
+
+main = quickCheck prop_EqC
