diff --git a/Example.hs b/Example.hs
new file mode 100644
--- /dev/null
+++ b/Example.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE TemplateHaskell #-}
+module Example where
+import Control.Monad
+import PartialTypeSigs
+import Language.Haskell.TH
+
+
+#if __GLASGOW_HASKELL__ > 707
+sigs
+    [| ["f1" :: a -> b -> (a, Int),
+        "f1" :: b -> a -> (Char, a) ] |]
+
+f1 x y | False = $(unionSigs [| f1 x y |])
+f1 x y = undefined -- (x,y)
+#endif
+
+
+sigs [| do
+  let f2 = undefined
+  Just
+    ( f2 :: a -> b -> (a, Int),
+      f2 :: c -> d -> (Char, d)
+    )
+  |]
+  
+f2 x y | False = $(unionSigs [| f2 x y |])
+f2 x y = undefined -- (x,y)
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, Adam Vogt <vogt.adam@gmail.com>
+
+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 Adam Vogt <vogt.adam@gmail.com> 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/PartialTypeSignatures.cabal b/PartialTypeSignatures.cabal
new file mode 100644
--- /dev/null
+++ b/PartialTypeSignatures.cabal
@@ -0,0 +1,21 @@
+name:                PartialTypeSignatures
+version:             0.1.0.0
+synopsis:            emulate partial type signatures with template haskell
+homepage:            http://code.haskell.org/~aavogt/PartialTypeSignatures
+license:             BSD3
+license-file:        LICENSE
+author:              Adam Vogt <vogt.adam@gmail.com>
+maintainer:          Adam Vogt <vogt.adam@gmail.com>
+category:            Development
+build-type:          Simple
+extra-source-files:  Example.hs
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     PartialTypeSigs
+  other-extensions:    TemplateHaskell, CPP
+  build-depends:       base <5,
+                       containers,
+                       template-haskell,
+                       syb
+  default-language:    Haskell2010
diff --git a/PartialTypeSigs.hs b/PartialTypeSigs.hs
new file mode 100644
--- /dev/null
+++ b/PartialTypeSigs.hs
@@ -0,0 +1,158 @@
+{-# LANGUAGE TemplateHaskell #-}
+{- | Description: template haskell to help emulate partial type signatures
+
+Example usage (GHC-7.8):
+
+> sigs
+>     [| ["f1" :: a -> b -> (a, Int),
+>         "f1" :: b -> a -> (Char, a) ] |]
+> 
+> f1 x y | False = $(unionSigs [| f1 x y |])
+> f1 x y = undefined -- (x,y)
+
+
+A GHC-7.6 compatible version must be slightly longer
+to work around the extra typechecking done of [| |]
+brackets:
+
+> sigs [| do
+>   f2 <- Nothing
+>   Just [ f2 :: a -> b -> (a, Int),
+>          f2 :: b -> a -> (Char, a) ]
+>   |]
+>   
+> f2 x y | False = $(unionSigs [| f2  x y |])
+> f2 x y = undefined -- (x,y)
+
+If the expression splice generated by 'unionSigs' is left out,
+
+> sigs
+>     [| ["g" :: a -> b -> (a, Int),
+>         "g" :: b -> a -> (Char, a) ] |]
+> 
+> g x y = undefined -- (x,y)
+
+then @g@'s type takes the most general type @(g :: t)@, and the two
+functions defined by 'sigs' can be used to restrict the type of g:
+
+> partialTypeSig_g1 :: (t -> t1 -> (t, Int)) -> t -> t1 -> (t, Int)
+> partialTypeSig_g1 = id
+> 
+> partialTypeSig_g2 :: (t -> t1 -> (Char, t1)) -> t -> t1 -> (Char, t1)
+> partialTypeSig_g2 = id
+
+-}
+module PartialTypeSigs
+  ( sigs,
+    unionSigs,
+   ) where
+
+
+import qualified Data.Map as M
+import Data.IORef
+import System.IO.Unsafe
+import Data.Maybe
+import Language.Haskell.TH
+import Data.Generics
+import Language.Haskell.TH.Syntax
+import Data.Monoid
+import Control.Monad
+import Data.Either
+
+{-# NOINLINE m #-}
+m :: IORef (M.Map String Int)
+m = unsafePerformIO (newIORef M.empty)
+
+{- ^ any subexpression of the passed-in expression which looks like:
+
+> "functionName" :: t
+> functionName :: t
+
+generates the following function:
+
+> partialTypeSig_functionName1 x = x `asTypeOf` (functionName `asTypeOf` (undefined :: t))
+
+Note that the above function is not the same as
+
+> badId x = x `asTypeOf` (functionName :: t)
+
+which requires that @t@ be more specific than @functionName@
+
+-}
+sigs :: ExpQ -> DecsQ
+sigs es = do
+    runIO $ writeIORef m M.empty
+    es <- es
+
+    let nts :: [(Exp, Type)]
+        nts = everything (<>)
+              ( \x -> [ (e,t) | SigE e t <- maybeToList (cast x) ])
+            es
+
+        (ntsGood, ntsBad) = partitionEithers 
+          $ map (\(e,t) -> case e of
+                  VarE (Name (OccName n) _nameFlavour) -> Left (n,t)
+                  LitE (StringL n) -> Left (n,t)
+                  _ -> Right e)
+            nts
+
+    unless (null ntsBad) $ reportWarning
+        $ "Don't know how to interpret the left-hand-side of '::':" ++ show ntsBad
+
+    fmap concat $ mapM (\(n,t) -> unifiesWith1 n (return t)) ntsGood
+    
+unifiesWithPrefix = "partialTypeSig_"
+
+{- | > unifiesWith1 "f" [t| forall a b c. a -> b -> c |]
+
+generates a function
+
+> partialTypeSig_f1 x = x `asTypeOf` (undefined :: a -> b -> c)
+
+-}
+unifiesWith1 :: String -> TypeQ -> DecsQ
+unifiesWith1 e t = do
+    k <- runIO $ atomicModifyIORef m $ \k ->
+          let k' = M.insertWith (+) e 1 k
+          in (k', fromMaybe 1 $ M.lookup e k')
+    unifiesWith2 (unifiesWithPrefix++e++show k) (dyn e) t
+
+unifiesWith2 :: String -> ExpQ -> TypeQ -> DecsQ
+unifiesWith2 s e t = do
+    x <- newName "x"
+    fmap (:[]) $ funD (mkName s)
+      [clause [varP x]
+      (normalB [| ($(varE x) `asTypeOf` $e) `asTypeOf` (undefined :: $t) |])
+      []]
+
+unionSigs :: ExpQ -> ExpQ
+unionSigs  call = do
+    call <- call
+    VarE (Name (OccName k) _) : args <- return $ reverse (unappsErev call)
+    m <- runIO (readIORef m)
+    maybe noCxt (toExp k args) $ M.lookup k m
+  where
+    noCxt = do
+      reportWarning $ "PartialTypeSigs.unionSigs: missing a call to PartialTypeSigs.sigs directly above"
+      [| error "PartialTypeSigs.unionSigs no context given" |]
+    toExp :: String -> [Exp] -> Int -> ExpQ
+    toExp k args n = 
+      foldr (\x y -> [| $x `asTypeOf` $y |])
+        [| error "PartialTypeSigs.unionSigs should be applied to an unreachable function clause" |]
+        [ foldl appE
+              [| $(dyn (unifiesWithPrefix++k++show i)) undefined |]
+              (map return args)
+            | i <- [1 .. n] ]
+
+{- | reverse of what you'd expect:
+
+> unappsErev <$> [| x (f y) z |]
+
+is equivalent to
+
+> sequence [ [| z |], [| f y |] , [| x |] ]@
+-}
+unappsErev :: Exp -> [Exp]
+unappsErev (AppE x y) = y : unappsErev x
+unappsErev (ConE x) | x == '() = []
+unappsErev x = [x]
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
