diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,14 @@
+Version 2.2
+-----------
+
+* Some types of arithmetic operations are different to aid in type inference.
+For example, `*|` does not normalize its dimension list.
+
+* The types of the `derive...` TH functions now allow for deriving units
+based on composite dimensions/units.
+
+* New TH function to help declare constants, called `declareConstant`.
+
 Version 2.1
 -----------
 
diff --git a/Data/Metrology/Combinators.hs b/Data/Metrology/Combinators.hs
--- a/Data/Metrology/Combinators.hs
+++ b/Data/Metrology/Combinators.hs
@@ -28,7 +28,8 @@
 data u1 :* u2 = u1 :* u2
 
 instance (Dimension d1, Dimension d2) => Dimension (d1 :* d2) where
-  type DimFactorsOf (d1 :* d2) = (DimFactorsOf d1) @+ (DimFactorsOf d2)
+  type DimFactorsOf (d1 :* d2)
+    = Normalize ((DimFactorsOf d1) @+ (DimFactorsOf d2))
 
 instance (Unit u1, Unit u2) => Unit (u1 :* u2) where
 
@@ -37,7 +38,8 @@
   type DimOfUnit (u1 :* u2) = DimOfUnit u1 :* DimOfUnit u2
   conversionRatio _ = undefined -- this should never be called
 
-  type UnitFactorsOf (u1 :* u2) = (UnitFactorsOf u1) @+ (UnitFactorsOf u2)
+  type UnitFactorsOf (u1 :* u2)
+    = Normalize ((UnitFactorsOf u1) @+ (UnitFactorsOf u2))
   canonicalConvRatio _ = canonicalConvRatio (undefined :: u1) *
                          canonicalConvRatio (undefined :: u2)
 
@@ -53,13 +55,15 @@
 data u1 :/ u2 = u1 :/ u2
 
 instance (Dimension d1, Dimension d2) => Dimension (d1 :/ d2) where
-  type DimFactorsOf (d1 :/ d2) = (DimFactorsOf d1) @- (DimFactorsOf d2)
+  type DimFactorsOf (d1 :/ d2)
+    = Normalize ((DimFactorsOf d1) @- (DimFactorsOf d2))
 
 instance (Unit u1, Unit u2) => Unit (u1 :/ u2) where
   type BaseUnit (u1 :/ u2) = Canonical
   type DimOfUnit (u1 :/ u2) = DimOfUnit u1 :/ DimOfUnit u2
   conversionRatio _ = undefined -- this should never be called
-  type UnitFactorsOf (u1 :/ u2) = (UnitFactorsOf u1) @- (UnitFactorsOf u2)
+  type UnitFactorsOf (u1 :/ u2)
+    = Normalize ((UnitFactorsOf u1) @- (UnitFactorsOf u2))
   canonicalConvRatio _ = canonicalConvRatio (undefined :: u1) /
                          canonicalConvRatio (undefined :: u2)
 
@@ -75,14 +79,16 @@
 data unit :^ (power :: Z) = unit :^ Sing power
 
 instance Dimension dim => Dimension (dim :^ power) where
-  type DimFactorsOf (dim :^ power) = (DimFactorsOf dim) @* power
+  type DimFactorsOf (dim :^ power)
+    = Normalize ((DimFactorsOf dim) @* power)
 
 instance (Unit unit, SingI power) => Unit (unit :^ power) where
   type BaseUnit (unit :^ power) = Canonical
   type DimOfUnit (unit :^ power) = DimOfUnit unit :^ power
   conversionRatio _ = undefined
 
-  type UnitFactorsOf (unit :^ power) = (UnitFactorsOf unit) @* power
+  type UnitFactorsOf (unit :^ power)
+    = Normalize ((UnitFactorsOf unit) @* power)
   canonicalConvRatio _ = canonicalConvRatio (undefined :: unit) ^^ (szToInt (sing :: Sing power))
 
 type instance DefaultUnitOfDim (d :^ z) = DefaultUnitOfDim d :^ z
diff --git a/Data/Metrology/Factor.hs b/Data/Metrology/Factor.hs
--- a/Data/Metrology/Factor.hs
+++ b/Data/Metrology/Factor.hs
@@ -88,9 +88,10 @@
 -- Reorder [] x ==> []
 -- @
 type family Reorder (a :: [Factor *]) (b :: [Factor *]) :: [Factor *] where
-  Reorder x x = x
-  Reorder '[] x = '[]
-  Reorder x '[] = x
+  Reorder x    x     = x
+  Reorder '[]  x     = '[]
+  Reorder '[x] y     = '[x]
+  Reorder x '[]      = x
   Reorder x (h ': t) = Reorder' (Extract h x) t
 
 -- | Helper function in 'Reorder'
diff --git a/Data/Metrology/Parser.hs b/Data/Metrology/Parser.hs
--- a/Data/Metrology/Parser.hs
+++ b/Data/Metrology/Parser.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE TemplateHaskell, CPP #-}
-
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Metrology.Parser
@@ -44,6 +42,9 @@
 -- @dam@ is ambiguous like this.
 -----------------------------------------------------------------------------
 
+{-# LANGUAGE TemplateHaskell, CPP #-}
+{-# OPTIONS_HADDOCK prune #-}
+
 module Data.Metrology.Parser (
   -- * Quasiquoting interface
   makeQuasiQuoter, allUnits, allPrefixes,
@@ -55,12 +56,15 @@
   -- necessary.
   parseUnit,
   UnitExp(..), SymbolTable,
-  mkSymbolTable
+  mkSymbolTable,
+
+  -- for internal use only
+  parseUnitExp, parseUnitType
   ) where
 
 import Prelude hiding ( exp )
 
-import Language.Haskell.TH
+import Language.Haskell.TH hiding ( Pred )
 import Language.Haskell.TH.Quote
 import Language.Haskell.TH.Desugar.Lift  ()  -- get the Lift Name instance
 import Data.Maybe
@@ -70,6 +74,49 @@
 import Data.Metrology
 import Data.Metrology.TH
 
+----------------------------------------------------------------------
+-- TH conversions
+----------------------------------------------------------------------
+
+parseUnitExp :: SymbolTable Name Name -> String -> Either String Exp
+parseUnitExp tab s = to_exp `liftM` parseUnit tab s   -- the Either monad
+  where
+    to_exp Unity                  = ConE 'Number
+    to_exp (Unit (Just pre) unit) = ConE '(:@) `AppE` of_type pre `AppE` of_type unit
+    to_exp (Unit Nothing unit)    = of_type unit
+    to_exp (Mult e1 e2)           = ConE '(:*) `AppE` to_exp e1 `AppE` to_exp e2
+    to_exp (Div e1 e2)            = ConE '(:/) `AppE` to_exp e1 `AppE` to_exp e2
+    to_exp (Pow e i)              = ConE '(:^) `AppE` to_exp e `AppE` mk_sing i
+
+    of_type :: Name -> Exp
+    of_type n = (VarE 'undefined) `SigE` (ConT n)
+
+    mk_sing :: Integer -> Exp
+    mk_sing n
+      | n < 0     = VarE 'sPred `AppE` mk_sing (n + 1)
+      | n > 0     = VarE 'sSucc `AppE` mk_sing (n - 1)
+      | otherwise = VarE 'sZero
+
+parseUnitType :: SymbolTable Name Name -> String -> Either String Type
+parseUnitType tab s = to_type `liftM` parseUnit tab s   -- the Either monad
+  where
+    to_type Unity                  = ConT ''Number
+    to_type (Unit (Just pre) unit) = ConT ''(:@) `AppT` ConT pre `AppT` ConT unit
+    to_type (Unit Nothing unit)    = ConT unit
+    to_type (Mult e1 e2)           = ConT ''(:*) `AppT` to_type e1 `AppT` to_type e2
+    to_type (Div e1 e2)            = ConT ''(:/) `AppT` to_type e1 `AppT` to_type e2
+    to_type (Pow e i)              = ConT ''(:^) `AppT` to_type e `AppT` mk_z i
+
+    mk_z :: Integer -> Type
+    mk_z n
+      | n < 0     = ConT ''Pred `AppT` mk_z (n + 1)
+      | n > 0     = ConT ''Succ `AppT` mk_z (n - 1)
+      | otherwise = ConT 'Zero   -- single quote as it's a data constructor!
+
+----------------------------------------------------------------------
+-- QuasiQuoters
+----------------------------------------------------------------------
+
 emptyQQ :: QuasiQuoter
 emptyQQ = QuasiQuoter { quoteExp = \_ -> fail "No quasi-quoter for expressions"
                       , quotePat = \_ -> fail "No quasi-quoter for patterns"
@@ -115,6 +162,10 @@
       prefix_pairs <- mapM mk_pair prefix_names
       unit_pairs   <- mapM mk_pair unit_names
       [| mkSymbolTable $( return $ ListE prefix_pairs ) $( return $ ListE unit_pairs ) |]
+
+----------------------------------------------------------------------
+-- Getting instances
+----------------------------------------------------------------------
 
 getInstanceNames :: Name -> Q [Name]
 getInstanceNames class_name = do
diff --git a/Data/Metrology/Parser/Internal.hs b/Data/Metrology/Parser/Internal.hs
--- a/Data/Metrology/Parser/Internal.hs
+++ b/Data/Metrology/Parser/Internal.hs
@@ -4,13 +4,12 @@
    This file defines a parser for unit expressions.
 -}
 
-{-# LANGUAGE LambdaCase, TemplateHaskell, NoMonomorphismRestriction,
-             FlexibleContexts, RankNTypes #-}
+{-# LANGUAGE LambdaCase, NoMonomorphismRestriction,
+             FlexibleContexts, RankNTypes, Safe #-}
 
 module Data.Metrology.Parser.Internal (
   UnitExp(..), parseUnit,
   
-  parseUnitExp, parseUnitType, 
   SymbolTable(..), mkSymbolTable,
   
   -- only for testing purposes:
@@ -29,10 +28,6 @@
 import Data.Maybe
 import Data.Char
 
-import Data.Metrology
-
-import Language.Haskell.TH hiding ( Pred )
-
 ----------------------------------------------------------------------
 -- Basic combinators
 ----------------------------------------------------------------------
@@ -159,7 +154,7 @@
 data SymbolTable pre u = SymbolTable { prefixTable :: PrefixTable pre
                                      , unitTable   :: UnitTable u
                                      }
-  deriving Show
+--  deriving Show
 
 -- build a Map from a list, checking for ambiguity
 unambFromList :: (Ord a, Show b) => [(a,b)] -> Either [(a,[String])] (Map.Map a b)
@@ -352,43 +347,4 @@
 parseUnit tab s = left show $ do
   toks <- lex s
   flip runReader tab $ runParserT (consumeAll parser) () "" toks
-
-----------------------------------------------------------------------
--- TH conversions
-----------------------------------------------------------------------
-
-parseUnitExp :: SymbolTable Name Name -> String -> Either String Exp
-parseUnitExp tab s = to_exp `liftM` parseUnit tab s   -- the Either monad
-  where
-    to_exp Unity                  = ConE 'Number
-    to_exp (Unit (Just pre) unit) = ConE '(:@) `AppE` of_type pre `AppE` of_type unit
-    to_exp (Unit Nothing unit)    = of_type unit
-    to_exp (Mult e1 e2)           = ConE '(:*) `AppE` to_exp e1 `AppE` to_exp e2
-    to_exp (Div e1 e2)            = ConE '(:/) `AppE` to_exp e1 `AppE` to_exp e2
-    to_exp (Pow e i)              = ConE '(:^) `AppE` to_exp e `AppE` mk_sing i
-
-    of_type :: Name -> Exp
-    of_type n = (VarE 'undefined) `SigE` (ConT n)
-
-    mk_sing :: Integer -> Exp
-    mk_sing n
-      | n < 0     = VarE 'sPred `AppE` mk_sing (n + 1)
-      | n > 0     = VarE 'sSucc `AppE` mk_sing (n - 1)
-      | otherwise = VarE 'sZero
-
-parseUnitType :: SymbolTable Name Name -> String -> Either String Type
-parseUnitType tab s = to_type `liftM` parseUnit tab s   -- the Either monad
-  where
-    to_type Unity                  = ConT ''Number
-    to_type (Unit (Just pre) unit) = ConT ''(:@) `AppT` ConT pre `AppT` ConT unit
-    to_type (Unit Nothing unit)    = ConT unit
-    to_type (Mult e1 e2)           = ConT ''(:*) `AppT` to_type e1 `AppT` to_type e2
-    to_type (Div e1 e2)            = ConT ''(:/) `AppT` to_type e1 `AppT` to_type e2
-    to_type (Pow e i)              = ConT ''(:^) `AppT` to_type e `AppT` mk_z i
-
-    mk_z :: Integer -> Type
-    mk_z n
-      | n < 0     = ConT ''Pred `AppT` mk_z (n + 1)
-      | n > 0     = ConT ''Succ `AppT` mk_z (n - 1)
-      | otherwise = ConT 'Zero   -- single quote as it's a data constructor!
 
diff --git a/Data/Metrology/Poly.hs b/Data/Metrology/Poly.hs
--- a/Data/Metrology/Poly.hs
+++ b/Data/Metrology/Poly.hs
@@ -229,14 +229,14 @@
 
 infixl 7 *| , |* , |/
 -- | Multiply a quantity by a scalar from the left
-(*|) :: Num n => n -> Qu b l n -> Qu (Normalize b) l n
+(*|) :: Num n => n -> Qu b l n -> Qu b l n
 a *| (Qu b) = Qu (a * b)
 
 -- | Multiply a quantity by a scalar from the right
-(|*) :: Num n => Qu a l n -> n -> Qu (Normalize a) l n
+(|*) :: Num n => Qu a l n -> n -> Qu a l n
 (Qu a) |* b = Qu (a * b)
 
 -- | Divide a quantity by a scalar
-(|/) :: Fractional n => Qu a l n -> n -> Qu (Normalize a) l n
+(|/) :: Fractional n => Qu a l n -> n -> Qu a l n
 (Qu a) |/ b = Qu (a / b)
 
diff --git a/Data/Metrology/Qu.hs b/Data/Metrology/Qu.hs
--- a/Data/Metrology/Qu.hs
+++ b/Data/Metrology/Qu.hs
@@ -211,12 +211,15 @@
 --- Instances for dimensionless quantities ------------------
 -------------------------------------------------------------
 
-deriving instance Num n => Num (Qu '[] l n)
-deriving instance Real n => Real (Qu '[] l n)
-deriving instance Fractional n => Fractional (Qu '[] l n)
-deriving instance Floating n => Floating (Qu '[] l n)
-deriving instance RealFrac n => RealFrac (Qu '[] l n)
-deriving instance RealFloat n => RealFloat (Qu '[] l n)
+-- Express the condition on `d` via a constraint, so that the
+-- requirement for the Num class can inform the choice of
+-- dimension. See #35.
+deriving instance (d ~ '[], Num n)        => Num (Qu d l n)
+deriving instance (d ~ '[], Real n)       => Real (Qu d l n)
+deriving instance (d ~ '[], Fractional n) => Fractional (Qu d l n)
+deriving instance (d ~ '[], Floating n)   => Floating (Qu d l n)
+deriving instance (d ~ '[], RealFrac n)   => RealFrac (Qu d l n)
+deriving instance (d ~ '[], RealFloat n)  => RealFloat (Qu d l n)
 
 -------------------------------------------------------------
 --- Combinators ---------------------------------------------
diff --git a/Data/Metrology/TH.hs b/Data/Metrology/TH.hs
--- a/Data/Metrology/TH.hs
+++ b/Data/Metrology/TH.hs
@@ -17,19 +17,21 @@
 module Data.Metrology.TH (
   evalType,
   declareDimension, declareCanonicalUnit, declareDerivedUnit, declareMonoUnit,
-
+  declareConstant,
+  
   -- for internal use only
   checkIsType                                    
   ) where
 
 import Language.Haskell.TH
-import Language.Haskell.TH.Desugar
-import Language.Haskell.TH.Desugar.Expand
+import Language.Haskell.TH.Desugar         ( dsType, sweeten )
+import Language.Haskell.TH.Desugar.Expand  ( expandType )
 import Language.Haskell.TH.Desugar.Lift ()   -- need Lift Rational
 
 import Data.Metrology.Dimensions
 import Data.Metrology.Units
 import Data.Metrology.LCSU
+import Data.Metrology.Poly
 
 -- | "Evaluates" a type as far as it can. This is useful, say, in instance
 -- declarations:
@@ -87,52 +89,47 @@
 
 -- | @declareCanonicalUnit unit_name dim (Just abbrev)@ creates a new
 -- canonical unit (that is, it is not defined in terms of other known units)
--- named @unit_name@, measuring dimension @dim@. (@dim@ must be the name of
--- the dimension /type/, not /data constructor/.) @abbrev@ will be the
+-- named @unit_name@, measuring dimension @dim@. @abbrev@ will be the
 -- abbreviation in the unit's @Show@ instance. If no abbraviation is supplied,
 -- then no @Show@ instance will be generated.
 --
 -- Example usage:
 --
--- > $(declareCanonicalUnit "Meter" ''Length (Just "m"))
-declareCanonicalUnit :: String -> Name -> Maybe String -> Q [Dec]
+-- > $(declareCanonicalUnit "Meter" [t| Length |] (Just "m"))
+declareCanonicalUnit :: String -> Q Type -> Maybe String -> Q [Dec]
 declareCanonicalUnit unit_name_str dim m_abbrev = do
-  checkIsType dim
   show_instance <- maybeMkShowInstance unit_name m_abbrev
   unit_instance <- [d| instance Unit $unit_type where
                          type BaseUnit $unit_type = Canonical
-                         type DimOfUnit $unit_type = $dim_type |]
+                         type DimOfUnit $unit_type = $dim |]
   return $ (DataD [] unit_name [] [NormalC unit_name []] [])
            : unit_instance ++ show_instance
   where
     unit_name = mkName unit_name_str
     unit_type = return $ ConT unit_name
-    dim_type = return $ ConT dim
 
 -- | @declareDerivedUnit unit_name base_unit_type ratio (Just abbrev)@ creates
--- a new derived unit, expressed in terms of @base_unit_type@ (which must be the
--- name of a /type/ not a /data constructor/). @ratio@ says how many base units
--- are in the derived unit. (Thus, if @unit_name@ is @"Minute"@ and @base_unit_type@
--- is @''Second@, then @ratio@ would be @60@.) @abbrev@, if supplied, becomes
--- the string produced in the derived unit's @Show@ instance. If no abbreviation
--- is supplied, no @Show@ instance is generated.
+-- a new derived unit, expressed in terms of @base_unit_type@. @ratio@ says
+-- how many base units are in the derived unit. (Thus, if @unit_name@ is
+-- @"Minute"@ and @base_unit_type@ is @''Second@, then @ratio@ would be @60@.)
+-- @abbrev@, if supplied, becomes the string produced in the derived unit's
+-- @Show@ instance. If no abbreviation is supplied, no @Show@ instance is
+-- generated.
 --
 -- Example usage:
 --
--- > $(declareDerivedUnit "Minute" ''Second 60 (Just "min"))
-declareDerivedUnit :: String -> Name -> Rational -> Maybe String -> Q [Dec]
+-- > $(declareDerivedUnit "Minute" [t| Second |] 60 (Just "min"))
+declareDerivedUnit :: String -> Q Type -> Rational -> Maybe String -> Q [Dec]
 declareDerivedUnit unit_name_str base_unit ratio m_abbrev = do
-  checkIsType base_unit
   show_instance <- maybeMkShowInstance unit_name m_abbrev
   unit_instance <- [d| instance Unit $unit_type where
-                         type BaseUnit $unit_type = $base_unit_type
+                         type BaseUnit $unit_type = $base_unit
                          conversionRatio _ = ratio |]
   return $ (DataD [] unit_name [] [NormalC unit_name []] [])
            : unit_instance ++ show_instance
   where
     unit_name = mkName unit_name_str
     unit_type = return $ ConT unit_name
-    base_unit_type = return $ ConT base_unit
 
 -- | @declareMonoUnit unit_name (Just abbrev)@ creates a new derived unit,
 -- intended for use without unit polymorphism. The same type stands for both
@@ -173,3 +170,36 @@
   where
     unit_name = mkName unit_name_str
     unit_type = return $ ConT unit_name
+
+-- | @declareConstant const_name value unit_type@ creates a new numerical
+-- constant, named @const_name@. Its numerical value is @value@ expressed
+-- in units given by @unit_type@. The constant is polymorphic in both its
+-- LCSU and numerical representation. For example,
+--
+-- > declareConstant "gravity_g" 9.80665 [t| Meter :/ Second :^ Two |]
+--
+-- yields
+--
+-- > gravity_g :: ( Fractional n
+-- >              , CompatibleUnit lcsu (Meter :/ Second :^ Two) )
+-- >           => MkQu_ULN (Meter :/ Second :^ Two) lcsu n
+-- > gravity_g = 9.80665 % (undefined :: Meter :/ Second :^ Two)
+declareConstant :: String -> Rational -> Q Type -> Q [Dec]
+declareConstant name value q_unit_type = do
+  unit_type <- q_unit_type
+  lcsu_name <- newName "lcsu"
+  n_name <- newName "n"
+  let lcsu = VarT lcsu_name
+      n    = VarT n_name
+      const_name = mkName name
+      const_type = ForallT [PlainTV lcsu_name, PlainTV n_name]
+                           [ ClassP ''Fractional [n]
+                           , ClassP ''CompatibleUnit [lcsu, unit_type] ] $
+                   ConT ''MkQu_ULN `AppT` unit_type `AppT` lcsu `AppT` n
+      ty_sig = SigD const_name const_type
+      dec    = ValD (VarP const_name) (NormalB $
+                                       VarE '(%) `AppE` LitE (RationalL value)
+                                                 `AppE` SigE (VarE 'undefined)
+                                                             unit_type) []
+  return [ty_sig, dec]
+                   
diff --git a/Data/Metrology/Vector.hs b/Data/Metrology/Vector.hs
--- a/Data/Metrology/Vector.hs
+++ b/Data/Metrology/Vector.hs
@@ -163,19 +163,19 @@
 
 infixl 7 |/
 -- | Divide a quantity by a scalar
-(|/) :: (VectorSpace n, Fractional (Scalar n)) => Qu a l n -> Scalar n -> Qu (Normalize a) l n
+(|/) :: (VectorSpace n, Fractional (Scalar n)) => Qu a l n -> Scalar n -> Qu a l n
 (Qu a) |/ b = Qu (a ^/ b)
 -- The above function should *not* need to be privileged. But, GHC can't figure
 -- out that a @@- '[] ~ a. Urgh.
 
 infixl 7 *| , |*
 -- | Multiply a quantity by a scalar from the left
-(*|) :: VectorSpace n => Scalar n -> Qu b l n -> Qu (Normalize b) l n
-a *| b = quantity a |*^| b
+(*|) :: VectorSpace n => Scalar n -> Qu b l n -> Qu b l n
+a *| (Qu b) =  Qu (a *^ b)
 
 -- | Multiply a quantity by a scalar from the right
-(|*) :: VectorSpace n => Qu a l n -> Scalar n -> Qu (Normalize a) l n
-a |* b = a |^*| quantity b
+(|*) :: VectorSpace n => Qu a l n -> Scalar n -> Qu a l n
+(Qu a) |* b = Qu (a ^* b)
 
 ---------------------------------------
 -- Multiplicative operations
diff --git a/Tests/Compile/EvalType.hs b/Tests/Compile/EvalType.hs
--- a/Tests/Compile/EvalType.hs
+++ b/Tests/Compile/EvalType.hs
@@ -2,7 +2,7 @@
    Copyright (c) 2014 Richard Eisenberg
 -}
 
-{-# LANGUAGE TemplateHaskell, FlexibleInstances, DataKinds #-}
+{-# LANGUAGE TemplateHaskell, FlexibleInstances, DataKinds, CPP #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Tests.Compile.EvalType where
@@ -14,3 +14,7 @@
 instance Show $(evalType [t| Length |]) where
   show x = x `showIn` Meter
 
+#if MIN_VERSION_th_desugar(1,5,0)
+instance Show $(evalType [t| Volume |]) where
+  show x = x `showIn` Liter
+#endif
diff --git a/Tests/Compile/TH.hs b/Tests/Compile/TH.hs
--- a/Tests/Compile/TH.hs
+++ b/Tests/Compile/TH.hs
@@ -7,8 +7,8 @@
 import qualified Data.Metrology as Mono
 
 $(declareDimension "Length")
-$(declareCanonicalUnit "Meter" ''Length (Just "m"))
-$(declareDerivedUnit "Foot" ''Meter 0.3048 Nothing)
+$(declareCanonicalUnit "Meter" [t| Length |] (Just "m"))
+$(declareDerivedUnit "Foot" [t| Meter |] 0.3048 Nothing)
 
 type MyLCSU = MkLCSU '[(Length, Meter)]
 
diff --git a/Tests/Linearity.hs b/Tests/Linearity.hs
new file mode 100644
--- /dev/null
+++ b/Tests/Linearity.hs
@@ -0,0 +1,30 @@
+{- Test the property of quantity as linear space
+   Copyright (c) 2014 Richard Eisenberg
+-}
+
+module Tests.Linearity where
+
+import Data.Metrology.Poly
+import Data.Metrology.Show ()
+import Data.Metrology.SI.Poly
+
+import Test.Tasty
+import Test.Tasty.HUnit
+
+len1 :: Length SI Rational
+len1 = 1 % Meter
+
+linearCompose :: (Fractional a) => a -> a -> Qu d l a  -> Qu d l a -> Qu d l a 
+linearCompose a b x y = a *| x |+| b *| y
+
+
+tests :: TestTree
+tests = testGroup "Show"
+  [ testCase "Identity" $ len1 @?= len1
+  , testCase "Addition" $ len1 |+| len1 @?= 2 *| len1 
+  , testCase "Summation of multiple quantities" $ 
+      qSum [len1,len1,len1] @?= 3 *| len1 
+  , testCase "Linear composition" $ 
+      linearCompose 0.2 0.8 len1 len1 @?= len1
+  ]
+
diff --git a/Tests/Main.hs b/Tests/Main.hs
--- a/Tests/Main.hs
+++ b/Tests/Main.hs
@@ -28,12 +28,14 @@
 
 import qualified Tests.Imperial
 import qualified Tests.LennardJones
+import qualified Tests.Linearity
 import qualified Tests.OffSystemAdd
 import qualified Tests.OffSystemCSU
 import qualified Tests.Parser
 import qualified Tests.PhysicalConstants
 import qualified Tests.Show
 import qualified Tests.Travel
+import qualified Tests.Vector
 
 import Test.Tasty
 
@@ -46,10 +48,12 @@
   testGroup "Tests"
   [ Tests.Imperial.tests
   , Tests.LennardJones.tests
+  , Tests.Linearity.tests    
   , Tests.OffSystemAdd.tests
   , Tests.OffSystemCSU.tests
   , Tests.Parser.tests
   , Tests.PhysicalConstants.tests
   , Tests.Show.tests
   , Tests.Travel.tests
+  , Tests.Vector.tests    
   ]
diff --git a/Tests/README.md b/Tests/README.md
new file mode 100644
--- /dev/null
+++ b/Tests/README.md
@@ -0,0 +1,19 @@
+`units` Test Design
+===================
+
+There are two kinds of test:
+
+ - `Compile` tests test only compilation, not any functionality. A new `Compile`
+   test should be placed in the `Compile` directory and imported from
+   `Tests.Main`, in alphabetical order with the others.
+
+ - Other tests test both compilation and some functionality. These use the
+   [`tasty`](http://hackage.haskell.org/package/tasty) testing framework,
+   avaiable on Hackage. Each of these tests should export a 
+   `tests :: TestTree` definition which contain all the tests in
+   the module. Then, this `tests` should be imported and run from within
+   `Tests.Main`, following the style there.
+
+To run the tests, just say `cabal test`. You will need to say `git submodule
+update --init` to download the contents of `units-defs`, necessary for testing
+purposes.
diff --git a/Tests/Vector.hs b/Tests/Vector.hs
new file mode 100644
--- /dev/null
+++ b/Tests/Vector.hs
@@ -0,0 +1,44 @@
+{-# LANGUAGE TypeFamilies #-}
+
+{- Test the property of vector quantity 
+   Copyright (c) 2014 Richard Eisenberg
+-}
+
+module Tests.Vector where
+
+import Data.Metrology.Vector
+import Data.Metrology.Show ()
+import Data.Metrology.SI.Poly
+import Data.VectorSpace
+
+import Test.Tasty
+import Test.Tasty.HUnit
+
+len1 :: Length SI Rational
+len1 = 1 % Meter
+
+
+type V2 = Length SI (Rational, Rational)    
+vec1 :: V2
+vec1 = (2,3) % Meter
+
+linearCompose :: (VectorSpace n, a ~ Scalar n) => a -> a -> Qu d l n  -> Qu d l n -> Qu d l n
+linearCompose a b x y = a *| x |+| b *| y
+
+
+tests :: TestTree
+tests = testGroup "Show"
+  [ testCase "Identity" $ vec1 @?= vec1
+  , testCase "Addition" $ vec1 |+| vec1 @?= 2 *| vec1 
+  , testCase "Summation of multiple quantities" $ 
+      qSum [vec1,vec1,vec1] @?= 3 *| vec1 
+  , testCase "Linear composition" $ 
+      linearCompose 0.2 0.8 vec1 vec1 @?= vec1
+
+  , testCase "Multiplication from right" $ 4 *| vec1 @?= vec1 |* 4
+  , testCase "Division by scalar" $ 10 *| vec1 @?= vec1 |/ 0.1
+
+  , testCase "scalar product" $
+      (5 % Meter) |*^| vec1 @?= ((10, 15) % (Meter :^ sTwo))
+  ]
+
diff --git a/units.cabal b/units.cabal
--- a/units.cabal
+++ b/units.cabal
@@ -1,8 +1,8 @@
 name:           units
-version:        2.1
+version:        2.2
 cabal-version:  >= 1.10
 synopsis:       A domain-specific type system for dimensional analysis
-homepage:       http://www.cis.upenn.edu/~eir/packages/units
+homepage:       https://github.com/goldfirere/units
 category:       Math
 author:         Richard Eisenberg <eir@cis.upenn.edu>
 maintainer:     Richard Eisenberg <eir@cis.upenn.edu>, Takayuki Muranushi <muranushi@gmail.com>
@@ -11,6 +11,7 @@
 extra-source-files: README.md
                   , CHANGES.md
                   , Tests/*.hs
+                  , Tests/README.md
                   , Tests/Compile/*.hs
                   , Tests/Compile/UnitParser/*.hs
                   , units-defs/Data/Metrology/*.hs
@@ -41,7 +42,7 @@
 source-repository this
   type:     git
   location: https://github.com/goldfirere/units.git
-  tag:      v2.1
+  tag:      v2.2
 
 library
   ghc-options: -Wall
@@ -79,8 +80,8 @@
     Data.Metrology.Parser.Internal
 
     -- cabal now recommends that TH be explicitly listed in cabal files
-  default-extensions: TemplateHaskell
-  default-language:   Haskell2010
+  other-extensions: TemplateHaskell
+  default-language: Haskell2010
 
 test-suite main
   type:             exitcode-stdio-1.0
@@ -103,7 +104,7 @@
   hs-source-dirs:   units-defs, .
 
     -- optimize compile time, not runtime!
-  ghc-options:        -O0 -Wall -Werror -main-is Tests.Main
+  ghc-options:        -O0 -Wall -main-is Tests.Main
 
     -- GHC 7.10 requires this in more places, and I don't feel like ferreting out exactly
     -- where.
