diff --git a/src/Language/Haskell/TH/Alpha.hs b/src/Language/Haskell/TH/Alpha.hs
--- a/src/Language/Haskell/TH/Alpha.hs
+++ b/src/Language/Haskell/TH/Alpha.hs
@@ -1,5 +1,10 @@
-{-# LANGUAGE NoMonomorphismRestriction, TypeFamilies, FlexibleInstances
-    , MultiParamTypeClasses, FunctionalDependencies #-}
+{-# LANGUAGE
+      FunctionalDependencies
+    , GeneralizedNewtypeDeriving
+    , RankNTypes
+    , FlexibleContexts
+    , BangPatterns
+    #-}
 {-|
 Module      : Language.Haskell.TH.Alpha
 Description : Alpha equivalence in TH
@@ -28,42 +33,121 @@
 
 module Language.Haskell.TH.Alpha (
     areExpAEq,
-    exp_equal,
+    expEqual,
+    (@=),
     AlphaEq(..)
     ) where
 
 import Language.Haskell.TH
-import Language.Haskell.TH.Syntax  (Quasi, returnQ)
+import Language.Haskell.TH.Syntax  (Quasi)
 import Language.Haskell.TH.Desugar
 import Data.Function               (on)
-import Control.Monad               (liftM, liftM2, liftM3, join, foldM)
-import Data.Data                   (toConstr, Data)
+import Control.Monad.State
+import Control.Monad.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Morph
 import Data.Maybe                  (isJust)
+import qualified Data.Map as Map
+import Control.Applicative
 
 
 
 --  A poor man's bound variable lookup table.
-type Lookup = ([(Name,Int)], [(Name,Int)], Int)
+type Lookup = (Map.Map Name Int, Map.Map Name Int, Int)
 
+emptyLookup :: Lookup
+emptyLookup = (Map.empty, Map.empty, 0)
+
+data LookupTbl = LookupTbl
+               { insertLR :: Name -> Name -> LookupTbl
+               , eqInTbl  :: Name -> Name -> Bool
+               , isInL    :: Name -> Bool
+               , isInR    :: Name -> Bool
+               }
+
+mapLookup :: Lookup -> LookupTbl
+mapLookup !(ls,rs,cnt) = LookupTbl
+           { insertLR = \a b -> mapLookup (Map.insert a cnt ls,
+                                           Map.insert b cnt rs,
+                                           cnt + 1)
+           , eqInTbl  = \a b -> Map.lookup a ls == Map.lookup b rs
+           , isInL    = \a   -> isJust $ Map.lookup a ls
+           , isInR    = \b   -> isJust $ Map.lookup b rs
+           }
+
+
+-- Monad holding lookup table if alpha equivalence is still possible,
+-- Nothing otherwise. Parametrized also on an extra monad 'm', which is
+-- needed for a single, unified interface for th and th-desugar types (the
+-- former will use a Quasi monad, the latter Identity).
+newtype LookupSTM m b = LookupST {
+    unLookupST :: StateT LookupTbl (MaybeT m) b
+    } deriving (Functor, Applicative, Monad, MonadState LookupTbl
+               , MonadPlus, Alternative)
+
+---------------------------------------------------------------------------
+-- Lifting and hoisting
+--
+--   This section is primarily concerned with making moving from a pure
+--   (Identity) context to other monads easy. We do this because desugaring
+--   (and other TH-related activities) end us up in some Quasi monad, so
+--   when a AlphaEq instance uses th-desugar for its arguments, but a pure
+--   function for its subexpressions, it ends up crossing a signature
+--   boundary that ideally shouldn't be annoying.
+---------------------------------------------------------------------------
+instance MonadTrans (LookupSTM) where
+    -- Laws:
+    --     1. lift . return == return
+    --        LookupST $ StateT (\tbl -> MaybeT $ return n >>= \x -> return $ Just (x, tbl))
+    --        LookupST $ StateT (\tbl -> MaybeT $ Just (n, tbl))
+    --     2. lift (m >>= f) == lift m >>= (lift . f)
+    lift m = LookupST $ StateT (\tbl -> MaybeT $ m >>= \x -> return $ Just (x, tbl))
+
+
+-- This is ugly, but the signature and name should explain it well enough.
+hoist' :: (Monad m) => (forall a . m a -> n a) -> LookupSTM m b -> LookupSTM n b
+hoist' nat lkstm = LookupST $ StateT (\tbl -> MaybeT . nat . runMaybeT $ runStateT (unLookupST lkstm) tbl)
+
+instance MFunctor LookupSTM where
+    hoist = hoist'
+
+toQ :: LookupST b -> LookupSTQ b
+toQ = hoist generalize
+
+type LookupST b  = LookupSTM Identity b
+type LookupSTQ b = LookupSTM Q b
+
+
+runLookupST :: Monad m => LookupSTM m a -> LookupTbl -> m (Maybe (a, LookupTbl))
+runLookupST st tbl = runMaybeT $ runStateT (unLookupST st) tbl
+
+runLookupST' :: LookupST a -> LookupTbl -> Maybe (a, LookupTbl)
+runLookupST' = (runIdentity .) . runLookupST
+
 -- | The main Alpha Equivalence class. '@=' is by default defined in terms
 -- of 'lkEq'. 'lkEq' is exposed for composability: it is easy to
 -- recursively build 'AlphaEq' instances from other 'AlphaEq' instances by
 -- delegating the lookup update to the subinstances.
-class AlphaEq a where
-    -- | Compares its arguments for alpha equivalence.
-    (@=) :: a -> a -> Bool
+class AlphaEq a m | a -> m where
     -- | Given a variable binding lookup compares arguments for alpha
-    -- equivalence, returning Just of updated lookup in case of
+    -- equivalence, setting the state to Just of updated lookup in case of
     -- equivalence, Nothing otherwise.
-    lkEq :: a -> a -> Lookup -> Maybe Lookup
-    x @= y = isJust $ lkEq x y ([], [], 0)
+    lkEq :: a -> a -> LookupSTM m ()
 
+-- | Compares its arguments for alpha equivalence. The default
+-- implementation uses Lookup for its LookupTbl, but more efficient
+-- datatypes can be used.
+(@=) :: (Monad m, AlphaEq a m) => a -> a -> m Bool
+x @= y = liftM isJust $ runLookupST (lkEq x y) (mapLookup emptyLookup)
 
+infix 4 @=     -- Same as (==)
+
+
 ---------------------------------------------------------------------------
 -- Exp
 ---------------------------------------------------------------------------
 
--- | Convenience function that uses 'runQ' on 'exp_equal'.
+-- | Convenience function that uses 'runQ' on 'expEqual'.
 --
 -- >>> areExpAEq [| let x = 5 in x |] [| let y = 5 in y |]
 -- True
@@ -71,144 +155,195 @@
          => ExpQ    -- ^ Quoted expression
          -> ExpQ    -- ^ Quoted expression
          -> m Bool
-areExpAEq e1 e2 = let expM = (join .) . liftM2 exp_equal
+areExpAEq e1 e2 = let expM = (join .) . liftM2 expEqual
                  in expM (runQ e1) (runQ e2)
 
--- | Compare two expressions for alpha-equivalence. Since this uses
--- th-desugar to desugar the expressions, returns a Bool in the Quasi
--- context.
-exp_equal :: Quasi m => Exp -> Exp -> m Bool
-exp_equal t1 t2 = (liftM3 exp_equal') (dsExp t1) (dsExp t2) (return ([], [], 0))
+instance AlphaEq Exp Q where
+        lkEq e1 e2 = do
+            e1' <- lift $ dsExp e1
+            e2' <- lift $ dsExp e2
+            toQ $ expEqual' e1' e2'
 
-instance AlphaEq DExp where
-        lkEq a b lk = if exp_equal' a b lk then Just lk else Nothing
 
-exp_equal' :: DExp -> DExp -> Lookup -> Bool
-exp_equal' (DVarE a) (DVarE b) (m1,m2,_) = lookup a m1 == lookup b m2
-exp_equal' (DConE a) (DConE b) (m1,m2,_) = lookup a m1 == lookup b m2
-                                        && (isJust $ lookup a m1)
-exp_equal' (DLitE l1) (DLitE l2) _       = l1 == l2
-exp_equal' (DAppE a1 a2) (DAppE b1 b2) c = (exp_equal' a1 b1 c)
-                                         && (exp_equal' a2 b2 c)
-exp_equal' (DLamE a1 a2) (DLamE b1 b2) (m1,m2,cnt) =
-        if ((/=) `on` length) a1 b1
-            then False
-            else exp_equal' a2 b2 ((ato a1 ++ m1),(ato b1 ++ m2), l)
-                where ato x = zip x [cnt..]
-                      l     = cnt + length a1
-exp_equal' (DCaseE a1 a2) (DCaseE b1 b2) c =
-        if length a2 == length b2
-            then exp_equal' a1 b1 c && (any id $ zipWith mec a2 b2)
-            else False
-        where mec x y = match_equal x y c
-exp_equal' (DLetE a1 a2) (DLetE b1 b2) c =
-        isJust (foldM lkEqC c (zip a1 b1) >>= lkEq a2 b2)
-        where lkEqC l (a,b) = lkEq a b l
-exp_equal' (DSigE a1 a2) (DSigE b1 b2) c@(m1,m2,_) =
-        lkEqB a1 b1 c && lkEqB a2 b2 c
-exp_equal' _ _ _ = False
+{--- | Compare two expressions for alpha-equivalence. Since this uses-}
+{--- th-desugar to desugar the expressions, returns a Bool in the Quasi-}
+{--- context.-}
+expEqual :: Quasi m => Exp -> Exp -> m Bool
+expEqual t1 t2 = do
+    t1' <- dsExp t1
+    t2' <- dsExp t2
+    let lkt = mapLookup emptyLookup
+    return $ isJust $ runLookupST' (lkEq t1' t2') lkt
 
----------------------------------------------------------------------------
--- Match
----------------------------------------------------------------------------
 
-match_equal :: DMatch -> DMatch -> Lookup -> Bool
-match_equal (DMatch pat1 exp1) (DMatch pat2 exp2) c =
-        case lkEq pat1 pat2 c of
-            Just d  -> exp_equal' exp1 exp2 d
-            Nothing -> False
+instance AlphaEq DExp Identity where
+    lkEq = expEqual'
 
----------------------------------------------------------------------------
--- LetDec
----------------------------------------------------------------------------
 
-instance AlphaEq DLetDec where
-        lkEq = letDec_equal
+expEqual' :: DExp -> DExp -> LookupST ()
+expEqual' (DVarE a1    ) (DVarE a2    ) = a1 ~=~ a2
+expEqual' (DConE a1    ) (DConE a2    ) = a1 ~=~ a2
+expEqual' (DLitE l1    ) (DLitE l2    ) = guard $ l1 == l2
+expEqual' (DAppE a1 b1 ) (DAppE a2 b2 ) = lkEq a1 a2 >> lkEq b1 b2
+expEqual' (DLamE a1 b1 ) (DLamE a2 b2 ) = do
+    guard $ ((==) `on` length) a1 a2
+    zipWithM_ insertLRLST a1 a2
+    lkEq b1 b2
+    return ()
+expEqual' (DCaseE a1 b1) (DCaseE a2 b2) = do
+    guard $ length b1 == length b2
+    lkEq a1 a2
+    zipWithM_ lkEq b1 b2
+    return ()
+expEqual' (DLetE a1 b1 ) (DLetE a2 b2 ) = zipWithM_ lkEq a1 a2 >> lkEq b1 b2
+expEqual' (DSigE a1 b1 ) (DSigE a2 b2 ) = lkEq a1 a2 >> lkEq b1 b2
+expEqual' _               _             = mzero
 
-letDec_equal :: DLetDec -> DLetDec -> Lookup -> Maybe Lookup
-letDec_equal (DFunD n1 cls1) (DFunD n2 cls2) c =
-        if n1 == n2 then foldM lkEqC c (zip cls1 cls2) else Nothing
-                    where lkEqC l (a,b) = lkEq a b l
-letDec_equal (DValD pat1 exp1) (DValD pat2 exp2) c =
-        lkEq exp1 exp2 c >>= lkEq pat1 pat2
-letDec_equal (DSigD name1 typ1) (DSigD name2 typ2) c@(m1,m2,_) =
-        -- Hard to tell how the name will be bound, so just check types
-        lkEq typ1 typ2 c
-letDec_equal (DInfixD fx1 name1) (DInfixD fx2 name2) c =
-        if fx1 == fx2 && name1 == name2 then Just c else Nothing
-letDec_equal _ _ _ = Nothing
+{-----------------------------------------------------------------------------}
+{--- Match-}
+{-----------------------------------------------------------------------------}
+instance AlphaEq DMatch Identity where
+        lkEq = matchEqual
 
----------------------------------------------------------------------------
--- LetDec
----------------------------------------------------------------------------
+matchEqual :: DMatch -> DMatch -> LookupST ()
+matchEqual (DMatch pat1 exp1) (DMatch pat2 exp2) = lkEq pat1 pat2
+                                                 >> lkEq exp1 exp2
 
-instance AlphaEq DType where
-        lkEq = type_equal
+{-----------------------------------------------------------------------------}
+{--- LetDec-}
+{-----------------------------------------------------------------------------}
 
--- TODO:
-type_equal :: DType -> DType -> Lookup -> Maybe Lookup
-type_equal (DForallT tybs1 ctx1 typ1) (DForallT tybs2 ctx2 typ2) c = do
-        nlk <- type_equal typ1 typ2 c
-        if all (\y -> cmpTYvar y nlk) (zip tybs1 tybs2)
-            then Just nlk
-            else Nothing
-     where cmpTYvar ((DPlainTV n1),(DPlainTV n2)) c' = cmpLk n1 n2 c'
-           cmpTYvar ((DKindedTV n1 k1),(DKindedTV n2 k2)) c' =
-                cmpLk n1 n2 c' && lkEqB k1 k2 c'
-           cmpTYvar _ _ = False
-type_equal (DAppT ty1 arg1) (DAppT ty2 arg2) c = undefined
-type_equal (DSigT ty1 knd1) (DAppT ty2 knd2) c = undefined
-type_equal (DVarT n1) (DVarT n2) c = undefined
+instance AlphaEq DLetDec Identity where
+    lkEq = letDecEqual
 
+letDecEqual :: DLetDec -> DLetDec -> LookupST ()
+letDecEqual (DFunD n1 cls1    ) (DFunD n2 cls2    ) = do
+    guard $ n1 == n2
+    zipWithM_ lkEq cls1 cls2
+letDecEqual (DValD pat1 exp1  ) (DValD pat2 exp2  ) =
+    lkEq exp1 exp2 >> lkEq pat1 pat2
+letDecEqual (DSigD _name1 typ1) (DSigD _name2 typ2) =
+    -- Hard to tell how the name will be bound, so just check types
+    lkEq typ1 typ2
+letDecEqual (DInfixD fx1 name1) (DInfixD fx2 name2) = guard $ fx1 == fx2
+                                                    && name1 == name2
+letDecEqual _                   _                   = mzero
+
+{-----------------------------------------------------------------------------}
+{--- Type-}
+{-----------------------------------------------------------------------------}
+
+instance AlphaEq DType Identity where
+    lkEq = typeEqual
+
+{--- TODO:-}
+typeEqual :: DType -> DType -> LookupST ()
+-- Type-level and value-level variable names don't conflict, so we can keep
+-- both in the same mapping
+typeEqual (DForallT tybs1 ctx1 typ1) (DForallT tybs2 ctx2 typ2) = do
+    zipWithM_ insertLRLSTty tybs1 tybs2
+    zipWithM_ lkEq ctx1 ctx2
+    lkEq typ1 typ2
+typeEqual (DAppT ty1 arg1          ) (DAppT ty2 arg2          ) =
+    lkEq ty1 ty2 >> lkEq arg1 arg2
+typeEqual (DSigT ty1 knd1          ) (DSigT ty2 knd2          ) = do
+    guard $ show knd1 == show knd2
+    lkEq ty1 ty2
+typeEqual (DConT n1                ) (DConT n2                ) =
+    guard $ show n1 == show n2
+typeEqual (DVarT n1                ) (DVarT n2                ) =
+    n1 ~=~ n2
+typeEqual _                          _                          = mzero
+
 ---------------------------------------------------------------------------
 -- Kind
 ---------------------------------------------------------------------------
--- TODO:
-instance AlphaEq DKind where
-        lkEq = undefined
+instance AlphaEq DKind Identity where
+    lkEq = kindEqual
 
+kindEqual :: DKind -> DKind -> LookupST ()
+kindEqual (DForallK ns1 typ1  ) (DForallK ns2 typ2  ) = do
+    zipWithM_ insertLRLST ns1 ns2
+    lkEq typ1 typ2
+kindEqual (DVarK n1           ) (DVarK n2           ) = n1 ~=~ n2
+{-kindEqual (DConK n1 knds1     ) (DConK n2 knds2     ) = n1 ~=~ n2-}
+kindEqual (DArrowK knda1 kndb1) (DArrowK knda2 kndb2) = lkEq knda1 knda2
+                                                      >> lkEq kndb1 kndb2
+kindEqual DStarK                DStarK                = return ()
+kindEqual _                     _                     = mzero
+
 ---------------------------------------------------------------------------
 -- Clause
 ---------------------------------------------------------------------------
-instance AlphaEq DClause where
-        lkEq = clause_equal
+instance AlphaEq DClause Identity where
+        lkEq = clauseEqual
 
-clause_equal :: DClause -> DClause -> Lookup -> Maybe Lookup
-clause_equal (DClause pats1 exp1) (DClause pats2 exp2) lk =
-        pat_res >>= lkEq exp1 exp2
-        where lkEqC l (a,b) = lkEq a b l
-              pat_res = foldM lkEqC lk (zip pats1 pats2)
+clauseEqual :: DClause -> DClause -> LookupST ()
+clauseEqual (DClause pats1 exp1) (DClause pats2 exp2) =
+    zipWithM_ lkEq pats1 pats2 >> lkEq exp1 exp2
 ---------------------------------------------------------------------------
+-- Clause
+---------------------------------------------------------------------------
+instance AlphaEq DPred Identity where
+    lkEq = predEqual
+
+predEqual :: DPred -> DPred -> LookupST ()
+predEqual (DAppPr pred1 typ1 ) (DAppPr pred2 typ2 ) = lkEq pred1 pred2
+                                                    >> lkEq typ1 typ2
+predEqual (DSigPr pred1 kind1) (DSigPr pred2 kind2) = lkEq pred1 pred2
+                                                    >> lkEq kind1 kind2
+predEqual (DVarPr n1         ) (DVarPr n2         ) = n1 ~=~ n2
+predEqual (DConPr n1         ) (DConPr n2         ) = n1 ~=~ n2
+predEqual _                    _                    = mzero
+
+---------------------------------------------------------------------------
 -- Pat
 ---------------------------------------------------------------------------
 
-instance AlphaEq DPat where
-        lkEq = pat_equal
+instance AlphaEq DPat Identity where
+    lkEq = patEqual
 
-pat_equal :: DPat -> DPat -> Lookup -> Maybe Lookup
-pat_equal (DLitPa lit1) (DLitPa lit2) c   = if lit1 == lit2
-                                                then Just c
-                                                else Nothing
-pat_equal (DVarPa n1) (DVarPa n2) c       = Just (addn n1 n2 c)
-    where addn x y (m1,m2,i) = ((x,i):m1,(y,i):m2,i+1)
-pat_equal (DConPa n1 p1) (DConPa n2 p2) c@(m1,m2,i)  =
-        if (lookup n1 m1 == lookup n2 m2 && length p1 == length p2)
-            then foldM cmbn c (zip p1 p2) -- Does this allow bindings across patterns?
-            else Nothing
-        where cmbn cn (x,y) = pat_equal x y c
-pat_equal (DTildePa pat1) (DTildePa pat2) c = pat_equal pat1 pat2 c
-pat_equal (DBangPa pat1) (DBangPa pat2)   c = pat_equal pat1 pat2 c
-pat_equal DWildPa DWildPa c               = Just c
-pat_equal _ _ _                           = Nothing
+patEqual :: DPat -> DPat -> LookupST ()
+patEqual (DLitPa lit1  ) (DLitPa lit2  ) = guard $ lit1 == lit2
+patEqual (DVarPa n1    ) (DVarPa n2    ) = insertLRLST  n1 n2
+patEqual (DConPa n1 p1 ) (DConPa n2 p2 ) = do
+     n1 ~=~ n2
+     guard $ length p1 == length p2
+     zipWithM_ lkEq p1 p2  -- Does this allow bindings across
+                           -- patterns?
+patEqual (DTildePa pat1) (DTildePa pat2) = lkEq pat1 pat2
+patEqual (DBangPa pat1 ) (DBangPa pat2 ) = lkEq pat1 pat2
+patEqual DWildPa         DWildPa         = return ()
+patEqual _               _               = mzero
 
 
 ---------------------------------------------------------------------------
 -- Utils
 ---------------------------------------------------------------------------
 
-fst3  (a,_,_) = a
-snd3  (_,b,_) = b
-thrd3 (_,_,c) = c
-cmpLk a b (m1,m2,_) = lookup a m1 == lookup b m2
-cmpLkC (a,b) c = cmpLk a b c
-lkEqB a b c = isJust $ lkEq a b c
+(~=~) :: Name -> Name -> LookupST ()
+a ~=~ b = do
+    tbl <- get
+    guard $ eqInTbl tbl a b
+    bol <- isInL' a
+    unless bol $ guard $ show a == show b
+
+
+isInL' :: Name -> LookupST Bool
+isInL' n = do
+    tbl <- get
+    return $ isInL tbl n
+
+
+insertLRLST :: Name -> Name -> LookupST ()
+insertLRLST a b = modify $ \tbl -> insertLR tbl a b
+
+insertLRLSTty :: DTyVarBndr -> DTyVarBndr -> LookupST ()
+insertLRLSTty (DPlainTV n1    ) (DPlainTV n2    ) = insertLRLST n1 n2
+insertLRLSTty (DKindedTV n1 k1) (DKindedTV n2 k2) = do
+    guard $ show k1 == show k2   -- Duck-show-template-kinding:
+                                 -- If it shows like a duck, it is
+                                 -- a duck
+    insertLRLST n1 n2
+insertLRLSTty _                 _                 = mzero
+
diff --git a/tests/tests.hs b/tests/tests.hs
--- a/tests/tests.hs
+++ b/tests/tests.hs
@@ -1,25 +1,31 @@
-{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TemplateHaskell  #-}
 module Main where
 
 import Test.Tasty
 import Test.Tasty.HUnit
 
-import Language.Haskell.TH
-import Control.Monad (liftM2, join)
 
+import Language.Haskell.TH
 import Language.Haskell.TH.Alpha
 
+main :: IO ()
 main = defaultMain tests
 
 
 tests :: TestTree
 tests = testGroup "Tests" [unitTests]
 
+unitTests :: TestTree
 unitTests = testGroup "Unit tests"
   [ testCase "Lambda expressions with different bound variables" $
     do
        b <- areExpAEq [| \x -> x|]  [| \y -> y|]
        assertBool "Expressions not considered equal!" b
+  , testCase "Nested lambda expressions with different bound variables" $
+    do
+       b <- areExpAEq [| \f -> \a -> \b -> f a b |]  [| \g -> \x -> \y -> g x y|]
+       assertBool "Expressions not considered equal!" b
+
   , testCase "Equal literals" $
     do
        b <- areExpAEq [| 5 |] [| 5 |]
@@ -31,6 +37,24 @@
   , testCase "Let bindings" $
     do
        b <- areExpAEq [| let x = 5 in x |] [| let y = 5 in y |]
+       assertBool "Expressions not considered equal!" b
+  , testCase "Different open terms" $
+    do
+       b <- areExpAEq [| tail |] [| head |]
+       assertBool "Expressions considered equal!" (not b)
+  , testCase "Same open terms" $
+    do
+       b <- areExpAEq [| tail |] [| tail |]
+       assertBool "Expressions not considered equal!" b
+  , testCase "Same lambda'd terms" $
+    do
+       b <- areExpAEq [| \x -> tail x |] [| \y -> tail y |]
+       assertBool "Expressions not considered equal!" b
+  , testCase "@=" $
+    do
+       let x = mkName "x"
+       let y = mkName "y"
+       b <- runQ $ (LamE [VarP x] (VarE x)) @= (LamE [VarP y] (VarE y))
        assertBool "Expressions not considered equal!" b
   ]
 
diff --git a/th-alpha.cabal b/th-alpha.cabal
--- a/th-alpha.cabal
+++ b/th-alpha.cabal
@@ -2,17 +2,24 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                th-alpha
-version:             0.1.0.2
+version:             0.2.0.0
 synopsis:            Alpha equivalence for TH Exp
 description:         
     Compare TH expressions (or clauses, patterns, etc.) for alpha equivalence.
     That is, compare for equality modulo the renaming of bound variables.
     .
-    >>> areExpAEq [| \x -> x |] [| \y -> y |]
-    True
+    > areExpAEq [| \x -> x |] [| \y -> y |]
+    > -- True
     .
+    > do
+    >    let x = mkName "x"
+    >    let y = mkName "y"
+    >    runQ $ (LamE [VarP x] (VarE x)) @= (LamE [VarP y] (VarE y))
+    > -- True
+    .
     This can be useful when for instance testing libraries that use Template 
     Haskell - usually correctness is only defined up to alpha equivalence.
+    
 license:             BSD3
 license-file:        LICENSE
 author:              Julian K. Arni
@@ -29,17 +36,25 @@
   exposed-modules:     Language.Haskell.TH.Alpha
   build-depends:       base >=4 && <5
                      , template-haskell 
+                     , containers
                      , th-desugar
+                     , mtl >=2 && <3
+                     , transformers
+                     , mmorph
   hs-source-dirs:      src
+  ghc-options:         -Wall
   default-language:    Haskell2010
 
 Test-Suite test
   type:                exitcode-stdio-1.0
   hs-source-dirs:      tests
+  ghc-options:         -Wall
   main-is:             tests.hs
   build-depends:       base >= 4 && < 5
                      , th-alpha
                      , template-haskell 
                      , tasty >= 0.8
                      , tasty-hunit
+                     , tasty-quickcheck
+                     , derive
   default-language:    Haskell2010
