diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,31 +1,31 @@
-Copyright (c) 2006-2014, Bjorn Buckwalter.
-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 the copyright holder(s) nor the names of
-    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.
+Copyright (c) 2006-2014, Bjorn Buckwalter.
+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 the copyright holder(s) nor the names of
+    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/Numeric/Units/Dimensional.lhs b/Numeric/Units/Dimensional.lhs
deleted file mode 100644
--- a/Numeric/Units/Dimensional.lhs
+++ /dev/null
@@ -1,662 +0,0 @@
-Numeric.Dimensional -- Statically checked physical dimensions
-Bjorn Buckwalter, bjorn.buckwalter@gmail.com
-License: BSD3
-
-
-= Summary =
-
-In this module we provide data types for performing arithmetic with
-physical quantities and units. Information about the physical
-dimensions of the quantities/units is embedded in their types and
-the validity of operations is verified by the type checker at compile
-time. The boxing and unboxing of numerical values as quantities is
-done by multiplication and division of units, of which an incomplete
-set is provided.
-
-We limit ourselves to "Newtonian" physics. We do not attempt to
-accommodate relativistic physics in which e.g. addition of length
-and time would be valid.
-
-As far as possible and/or practical the conventions and guidelines
-of NIST's "Guide for the Use of the International System of Units
-(SI)" [1] are followed. Occasionally we will reference specific
-sections from the guide and deviations will be explained.
-
-
-= Disclaimer =
-
-Merely an engineer, the author doubtlessly uses a language and
-notation that makes mathematicians and physicist cringe. He does
-not mind constructive criticism (or darcs patches).
-
-The sets of functions and units defined herein are incomplete and
-reflect only the author's needs to date. Again, patches are welcome.
-
-The author has elected to keep the module detached from the standard(?)
-Haskell library hierarchy. In part because the module name space
-layout seems to be an open issue and in part because he is unsure
-where to fit it in.
-
-
-= Preliminaries =
-
-This module requires GHC 6.6 or later. We utilize multi-parameter
-type classes, phantom types, functional dependencies and undecidable
-instances (and possibly additional unidentified GHC extensions).
-Clients of the module are generally not required to use these
-extensions.
-
-> {-# LANGUAGE UndecidableInstances
->            , ScopedTypeVariables
->            , EmptyDataDecls
->            , MultiParamTypeClasses
->            , FunctionalDependencies
->            , FlexibleInstances
->            , TypeSynonymInstances
->            , FlexibleContexts
->            , GeneralizedNewtypeDeriving
->            , DeriveDataTypeable
-> #-}
-
-> {- |
->    Copyright  : Copyright (C) 2006-2013 Bjorn Buckwalter
->    License    : BSD3
->
->    Maintainer : bjorn.buckwalter@gmail.com
->    Stability  : Stable
->    Portability: GHC only?
->
-> Please refer to the literate Haskell code for documentation of both API
-> and implementation.
-> -}
-
-> module Numeric.Units.Dimensional
->       -- TODO discriminate exports, in particular Variants and Dims.
->   where
-
-> import Prelude
->   ( Show, Eq, Ord, Enum, Num, Fractional, Floating, RealFloat, Functor, fmap
->   , (.), flip, show, (++), undefined, otherwise, (==), String, unwords
->   , map, foldr, null, Integer
->   )
-> import qualified Prelude
-> import Data.List (genericLength)
-> import Data.Maybe (Maybe (Just, Nothing), catMaybes)
-> import Data.Typeable (Typeable)
-> import Numeric.NumType
->   ( NumType, NonZero, PosType, Zero, toNum, Sum
->   , Pos1, Pos2, pos2, Pos3, pos3
->   )
-> import qualified Numeric.NumType as N (Mul, Div)
-
-We will reuse the operators and function names from the Prelude.
-To prevent unpleasant surprises we give operators the same fixity
-as the Prelude.
-
-> infixr 8  ^, ^+, ^/, **
-> infixl 7  *, /
-> infixl 6  +, -
-
-
-= Dimensional =
-
-Our primary objective is to define a data type that can be used to
-represent (while still differentiating between) units and quantities.
-There are two reasons for consolidating units and quantities in one
-data type. The first being to allow code reuse as they are largely
-subject to the same operations. The second being that it allows
-reuse of operators (and functions) between the two without resorting
-to occasionally cumbersome type classes.
-
-We call this data type 'Dimensional' to capture the notion that the
-units and quantities it represents have physical dimensions.
-
-> newtype Dimensional v d a = Dimensional a deriving (Eq, Ord, Enum, Typeable)
-
-The type variable 'a' is the only non-phantom type variable and
-represents the numerical value of a quantity or the scale (w.r.t.
-SI units) of a unit. For SI units the scale will always be 1. For
-non-SI units the scale is the ratio of the unit to the SI unit with
-the same physical dimension.
-
-Since 'a' is the only non-phantom type we were able to define
-'Dimensional' as a newtype, avoiding boxing at runtime.
-
-
-= The variety 'v' of 'Dimensional' =
-
-The phantom type variable v is used to distinguish between units
-and quantities. It should be one of the following:
-
-> data DUnit deriving Typeable
-> data DQuantity deriving Typeable
-
-For convenience we define type synonyms for units and quantities.
-
-> type Unit     = Dimensional DUnit
-> type Quantity = Dimensional DQuantity
-
-The relationship between (the value of) a 'Quantity', its numerical
-value and its 'Unit' is described in 7.1 "Value and numerical value
-of a quantity" of [1]. In short a 'Quantity' is the product of a
-number and a 'Unit'. We define the '(*~)' operator as a convenient
-way to declare quantities as such a product.
-
-> (*~) :: Num a => a -> Unit d a -> Quantity d a
-> x *~ Dimensional y = Dimensional (x Prelude.* y)
-
-Conversely, the numerical value of a 'Quantity' is obtained by
-dividing the 'Quantity' by its 'Unit' (any unit with the same
-physical dimension). The '(/~)' operator provides a convenient way
-of obtaining the numerical value of a quantity.
-
-> (/~) :: Fractional a => Quantity d a -> Unit d a -> a
-> Dimensional x /~ Dimensional y = x Prelude./ y
-
-We give '*~' and '/~' the same fixity as '*' and '/' defined below.
-Note that this necessitates the use of parenthesis when composing
-units using '*' and '/', e.g. "1 *~ (meter / second)".
-
-> infixl 7  *~, /~
-
-
-= The dimension 'd' of 'Dimensional' =
-
-The phantom type variable d encompasses the physical dimension of
-the 'Dimensional'. As detailed in [5] there are seven base dimensions,
-which can be combined in integer powers to a given physical dimension.
-We represent physical dimensions as the powers of the seven base
-dimensions that make up the given dimension. The powers are represented
-using NumTypes. For convenience we collect all seven base dimensions
-in a data type 'Dim'.
-
-> data Dim l m t i th n j deriving Typeable
-
-where the respective dimensions are represented by type variables
-using the following convention.
-
-    l  -- Length
-    m  -- Mass
-    t  -- Time
-    i  -- Electric current
-    th -- Thermodynamic temperature
-    n  -- Amount of substance
-    j  -- Luminous intensity
-
-We could have chosen to provide type variables for the seven base
-dimensions in 'Dimensional' instead of creating a new data type
-'Dim'. However, that would have made any type signatures involving
-'Dimensional' very cumbersome.  By encompassing the physical dimension
-in a single type variable we can "hide" the cumbersome type arithmetic
-behind convenient type classes as will be seen later.
-
-Using our 'Dim' data type we define some type synonyms for convenience
-and illustrative purposes. We start with the base dimensions.
-
-> type DOne         = Dim Zero Zero Zero Zero Zero Zero Zero
-> type DLength      = Dim Pos1 Zero Zero Zero Zero Zero Zero
-> type DMass        = Dim Zero Pos1 Zero Zero Zero Zero Zero
-> type DTime        = Dim Zero Zero Pos1 Zero Zero Zero Zero
-> type DElectricCurrent          = Dim Zero Zero Zero Pos1 Zero Zero Zero
-> type DThermodynamicTemperature = Dim Zero Zero Zero Zero Pos1 Zero Zero
-> type DAmountOfSubstance        = Dim Zero Zero Zero Zero Zero Pos1 Zero
-> type DLuminousIntensity        = Dim Zero Zero Zero Zero Zero Zero Pos1
-
-Using the above type synonyms we can define type synonyms for
-quantities of particular physical dimensions.
-
-Quantities with the base dimensions.
-
-> type Dimensionless            = Quantity DOne
-> type Length                   = Quantity DLength
-> type Mass                     = Quantity DMass
-> type Time                     = Quantity DTime
-> type ElectricCurrent          = Quantity DElectricCurrent
-> type ThermodynamicTemperature = Quantity DThermodynamicTemperature
-> type AmountOfSubstance        = Quantity DAmountOfSubstance
-> type LuminousIntensity        = Quantity DLuminousIntensity
-
-
-= Arithmetic on physical dimensions =
-
-When performing arithmetic on units and quantities the arithmetics
-must be applied to both the numerical values of the Dimensionals
-but also to their physical dimensions. The type level arithmetic
-on physical dimensions is governed by multi-parameter type classes
-and functional dependences.
-
-Multiplication of dimensions corresponds to adding of the base
-dimensions' exponents.
-
-> class Mul d d' d'' | d d' -> d''
-> instance (Sum l  l'  l'',
->           Sum m  m'  m'',
->           Sum t  t'  t'',
->           Sum i  i'  i'',
->           Sum th th' th'',
->           Sum n  n'  n'',
->           Sum j  j'  j'') => Mul (Dim l   m   t   i   th   n   j)
->                                  (Dim l'  m'  t'  i'  th'  n'  j')
->                                  (Dim l'' m'' t'' i'' th'' n'' j'')
-
-Division of dimensions corresponds to subtraction of the base
-dimensions' exponents.
-
-> class Div d d' d'' | d d' -> d''
-> instance (Sum l  l'  l'',
->           Sum m  m'  m'',
->           Sum t  t'  t'',
->           Sum i  i'  i'',
->           Sum th th' th'',
->           Sum n  n'  n'',
->           Sum j  j'  j'') => Div (Dim l'' m'' t'' i'' th'' n'' j'')
->                                  (Dim l'  m'  t'  i'  th'  n'  j')
->                                  (Dim l   m   t   i   th   n   j)
-
-We could provide the 'Mul' and 'Div' classes with full functional
-dependencies but that would be of limited utility as there is no
-obvious use for "backwards" type inference and would also limit
-what we can achieve overlapping instances. (In particular, it breaks
-the 'Extensible' module.)
-
-We limit ourselves to integer powers of Dimensionals as fractional
-powers make little physical sense. Since the value of the exponent
-affects the type of the result the value of the exponent must be
-visible to the type system, therefore we will generally represent
-the exponent with a 'NumType'.
-
-Powers of dimensions corresponds to multiplication of the base
-dimensions' exponents by the exponent.
-
-> class (NumType x) => Pow d x d' | d x -> d'
-> instance (N.Mul l  x l',
->           N.Mul m  x m',
->           N.Mul t  x t',
->           N.Mul i  x i',
->           N.Mul th x th',
->           N.Mul n  x n',
->           N.Mul j  x j') => Pow (Dim l  m  t  i  th  n  j) x
->                                 (Dim l' m' t' i' th' n' j')
-
-Roots of dimensions corresponds to division of the base dimensions'
-exponents by order(?) of the root.
-
-> class (NonZero x) => Root d x d' | d x -> d'
-> instance (N.Div l  x l',
->           N.Div m  x m',
->           N.Div t  x t',
->           N.Div i  x i',
->           N.Div th x th',
->           N.Div n  x n',
->           N.Div j  x j') => Root (Dim l  m  t  i  th  n  j) x
->                                  (Dim l' m' t' i' th' n' j')
-
-
-= Arithmetic on units and quantities =
-
-Thanks to the arithmetic on physical dimensions having been sorted
-out separately a lot of the arithmetic on Dimensionals is straight
-forward. In particular the type signatures are much simplified.
-
-Multiplication, division and powers apply to both units and quantities.
-
-> (*) :: (Num a, Mul d d' d'')
->     => Dimensional v d a -> Dimensional v d' a -> Dimensional v d'' a
-> Dimensional x * Dimensional y = Dimensional (x Prelude.* y)
-
-> (/) :: (Fractional a, Div d d' d'')
->     => Dimensional v d a -> Dimensional v d' a -> Dimensional v d'' a
-> Dimensional x / Dimensional y = Dimensional (x Prelude./ y)
-
-> (^) :: (Fractional a, Pow d n d')
->     => Dimensional v d a -> n -> Dimensional v d' a
-> Dimensional x ^ n = Dimensional (x Prelude.^^ (toNum n :: Integer))
-
-In the unlikely case someone needs to use this library with
-non-fractional numbers we provide the alternative power operator
-'^+' that is restricted to positive exponents.
-
-> (^+) :: (Num a, PosType n, Pow d n d')
->      => Dimensional v d a -> n -> Dimensional v d' a
-> Dimensional x ^+ n = Dimensional (x Prelude.^ (toNum n :: Integer))
-
-A special case is that dimensionless quantities are not restricted
-to integer exponents. This is accommodated by the '**' operator
-defined later.
-
-
-= Quantity operations =
-
-Some additional operations obviously only make sense for quantities.
-Of these, negation, addition and subtraction are particularly simple
-as they are done in a single physical dimension.
-
-> negate :: (Num a) => Quantity d a -> Quantity d a
-> negate (Dimensional x) = Dimensional (Prelude.negate x)
-
-> (+) :: (Num a) => Quantity d a -> Quantity d a -> Quantity d a
-> Dimensional x + Dimensional y = Dimensional (x Prelude.+ y)
-
-> (-) :: (Num a) => Quantity d a -> Quantity d a -> Quantity d a
-> x - y = x + negate y
-
-Absolute value.
-
-> abs :: (Num a) => Quantity d a -> Quantity d a
-> abs (Dimensional x) = Dimensional (Prelude.abs x)
-
-Roots of arbitrary (integral) degree. Appears to occasionally be useful
-for units as well as quantities.
-
-> nroot :: (Floating a, Root d n d') => n -> Dimensional v d a -> Dimensional v d' a
-> nroot n (Dimensional x) = Dimensional (x Prelude.** (1 Prelude./ toNum n))
-
-We provide short-hands for the square and cubic roots.
-
-> sqrt :: (Floating a, Root d Pos2 d') => Dimensional v d a -> Dimensional v d' a
-> sqrt = nroot pos2
-> cbrt :: (Floating a, Root d Pos3 d') => Dimensional v d a -> Dimensional v d' a
-> cbrt = nroot pos3
-
-We also provide an operator alternative to nroot for those that
-prefer such.
-
-> (^/) :: (Floating a, Root d n d') => Dimensional v d a -> n -> Dimensional v d' a
-> (^/) = flip nroot
-
-
-= List functions =
-
-Here we define operators and functions to make working with homogenuous
-lists of dimensionals more convenient.
-
-We define two convenience operators for applying units to all
-elements of a functor (e.g. a list).
-
-> (*~~) :: (Functor f, Num a) => f a -> Unit d a -> f (Quantity d a)
-> xs *~~ u = fmap (*~ u) xs
-
-> (/~~) :: (Functor f, Fractional a) => f (Quantity d a) -> Unit d a -> f a
-> xs /~~ u = fmap (/~ u) xs
-
-> infixl 7  *~~, /~~
-
-The sum of all elements in a list.
-
-> sum :: forall d a . Num a => [Quantity d a] -> Quantity d a
-> sum = foldr (+) _0
-
-The length of the list as a 'Dimensionless'. This can be useful for
-purposes of e.g. calculating averages.
-
-> dimensionlessLength :: Num a => [Dimensional v d a] -> Dimensionless a
-> dimensionlessLength = Dimensional . genericLength
-
-
-= Dimensionless =
-
-For dimensionless quantities pretty much any operation is applicable.
-We provide this freedom by making 'Dimensionless' an instance of
-'Functor'.
-
-> instance Functor Dimensionless where
->   fmap f (Dimensional x) = Dimensional (f x)
-
-We continue by defining elementary functions on 'Dimensionless'
-that may be obviously useful.
-
-> exp, log, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh
->   :: (Floating a) => Dimensionless a -> Dimensionless a
-> exp   = fmap Prelude.exp
-> log   = fmap Prelude.log
-> sin   = fmap Prelude.sin
-> cos   = fmap Prelude.cos
-> tan   = fmap Prelude.tan
-> asin  = fmap Prelude.asin
-> acos  = fmap Prelude.acos
-> atan  = fmap Prelude.atan
-> sinh  = fmap Prelude.sinh
-> cosh  = fmap Prelude.cosh
-> tanh  = fmap Prelude.tanh
-> asinh = fmap Prelude.asinh
-> acosh = fmap Prelude.acosh
-> atanh = fmap Prelude.atanh
-
-> (**) :: (Floating a)
->      => Dimensionless a -> Dimensionless a -> Dimensionless a
-> Dimensional x ** Dimensional y = Dimensional (x Prelude.** y)
-
-For 'atan2' the operands need not be dimensionless but they must be
-of the same type. The result will of course always be dimensionless.
-
-> atan2 :: (RealFloat a)
->       => Quantity d a -> Quantity d a -> Dimensionless a
-> atan2 (Dimensional y) (Dimensional x) = Dimensional (Prelude.atan2 y x)
-
-The only unit we will define in this module is 'one'. The unit one
-has dimension one and is the base unit of dimensionless values. As
-detailed in 7.10 "Values of quantities expressed simply as numbers:
-the unit one, symbol 1" of [1] the unit one generally does not
-appear in expressions. However, for us it is necessary to use 'one'
-as we would any other unit to perform the "boxing" of dimensionless
-values.
-
-> one :: Num a => Unit DOne a
-> one = Dimensional 1
-
-For convenience we define some constants for small integer values
-that often show up in formulae. We also throw in 'pi' and 'tau' for
-good measure.
-
-The constant for zero is polymorphic as proposed by Douglas McClean
-(http://code.google.com/p/dimensional/issues/detail?id=39) allowing
-it to express zero Length or Capacitance or Velocity etc, in addition
-to the dimensionless value zero.
-
-> _0 :: (Num a) => Quantity d a
-> _0 = Dimensional 0
-
-> _1, _2, _3, _4, _5, _6, _7, _8, _9 :: (Num a) => Dimensionless a
-> _1 = 1 *~ one
-> _2 = 2 *~ one
-> _3 = 3 *~ one
-> _4 = 4 *~ one
-> _5 = 5 *~ one
-> _6 = 6 *~ one
-> _7 = 7 *~ one
-> _8 = 8 *~ one
-> _9 = 9 *~ one
-
-For background on 'tau' see http://tauday.com/tau-manifesto (but also
-feel free to review http://www.thepimanifesto.com).
-
-> pi, tau :: (Floating a) => Dimensionless a
-> pi = Prelude.pi *~ one
-> tau = _2 * pi
-
-
-= Instances of 'Show' =
-
-We will conclude by providing a reasonable 'Show' instance for
-quantities. We neglect units since it is unclear how to represent them
-in a way that distinguishes them from quantities, or whether that is
-even a requirement.
-
-> instance forall d a. (Show d, Show a) => Show (Quantity d a) where
->   show (Dimensional x) = show x ++ if (null unit) then "" else " " ++ unit
->       where unit = show (undefined :: d)
-
-The above implementation of 'show' relies on the dimension 'd' being an
-instance of 'Show'. The "normalized" unit of the quantity can be inferred
-from its dimension.
-
-> instance forall l m t i th n j.
->   ( NumType l
->   , NumType m
->   , NumType t
->   , NumType i
->   , NumType th
->   , NumType n
->   , NumType j
->   ) => Show (Dim l m t i th n j) where
->   show _ = (unwords . catMaybes)
->            [ dimUnit "m"   (undefined :: l)
->            , dimUnit "kg"  (undefined :: m)
->            , dimUnit "s"   (undefined :: t)
->            , dimUnit "A"   (undefined :: i)
->            , dimUnit "K"   (undefined :: th)
->            , dimUnit "mol" (undefined :: n)
->            , dimUnit "cd"  (undefined :: j)
->            ]
-
-The helper function 'dimUnit' defined next conditions a 'String' (unit)
-with an exponent, if appropriate. The reason we define 'dimUnit' at the
-top-level rather than in the where-clause is that it may be useful for
-users of the 'Extensible' module.
-
-> dimUnit :: (NumType n) => String -> n -> Maybe String
-> dimUnit u n
->   | x == 0    = Nothing
->   | x == 1    = Just u
->   | otherwise = Just (u ++ "^" ++ show x)
->   where x = toNum n :: Integer
-
-
-= The 'prefix' function =
-
-We will define a 'prefix' function which applies a scale factor to
-a unit. The 'prefix' function will be used by other modules to
-define the SI prefixes and non-SI units.
-
-> prefix :: (Num a) => a -> Unit d a -> Unit d a
-> prefix x (Dimensional y) = Dimensional (x Prelude.* y)
-
-
-= Conclusion and usage =
-
-We have defined operators and units that allow us to define and
-work with physical quantities. A physical quantity is defined by
-multiplying a number with a unit (the type signature is optional).
-
-] v :: Velocity Prelude.Double
-] v = 90 *~ (kilo meter / hour)
-
-It follows naturally that the numerical value of a quantity is
-obtained by division by a unit.
-
-] numval :: Prelude.Double
-] numval = v /~ (meter / second)
-
-The notion of a quantity as the product of a numerical value and a
-unit is supported by 7.1 "Value and numerical value of a quantity" of
-[1]. While the above syntax is fairly natural it is unfortunate that
-it must violate a number of the guidelines in [1], in particular 9.3
-"Spelling unit names with prefixes", 9.4 "Spelling unit names obtained
-by multiplication", 9.5 "Spelling unit names obtained by division".
-
-As a more elaborate example of how to use the module we define a
-function for calculating the escape velocity of a celestial body
-[2].
-
-] escapeVelocity :: (Floating a) => Mass a -> Length a -> Velocity a
-] escapeVelocity m r = sqrt (two * g * m / r)
-]   where
-]       two = 2 *~ one
-]       g = 6.6720e-11 *~ (newton * meter ^ pos2 / kilo gram ^ pos2)
-
-The following is an example GHC session where the above function
-is used to calculate the escape velocity of Earth in kilometer per
-second.
-
-  *Numeric.Dimensional> :set +t
-  *Numeric.Dimensional> let me = 5.9742e24 *~ kilo gram -- Mass of Earth.
-  me :: Quantity DMass GHC.Float.Double
-  *Numeric.Dimensional> let re = 6372.792 *~ kilo meter -- Mean radius of Earth.
-  re :: Quantity DLength GHC.Float.Double
-  *Numeric.Dimensional> let ve = escapeVelocity me re   -- Escape velocity of Earth.
-  ve :: Velocity GHC.Float.Double
-  *Numeric.Dimensional> ve /~ (kilo meter / second)
-  11.184537332296259
-  it :: GHC.Float.Double
-
-For completeness we should also show an example of the error messages
-we will get from GHC when performing invalid arithmetic. In the
-best case GHC will be able to use the type synonyms we have defined
-in its error messages.
-
-] x = 1 *~ meter + 1 *~ second
-
-    Couldn't match expected type `Pos1' against inferred type `Zero'
-      Expected type: Unit DLength t
-      Inferred type: Unit DTime a
-    In the second argument of `(*~)', namely `second'
-    In the second argument of `(+)', namely `1 *~ second'
-
-In other cases the error messages aren't very friendly.
-
-] x = 1 *~ meter / (1 *~ second) + 1 *~ kilo gram
-
-    Couldn't match expected type `Zero'
-           against inferred type `Neg Zero'
-    When using functional dependencies to combine
-      Sub Zero (Pos Zero) (Neg Zero),
-        arising from use of `/' at Numeric/Dimensional.lhs:425:9-20
-      Sub Zero (Pos Zero) Zero,
-        arising from use of `/' at Numeric/Dimensional.lhs:532:5-30
-
-It is the author's experience that the usefullness of the compiler
-error messages is more often than not limited to pinpointing the
-location of errors.
-
-
-= Future work =
-
-While there is an insane amount of units in use around the world
-it is reasonable to provide at least all SI units. Units outside
-of SI will most likely be added on an as-needed basis.
-
-There are also plenty of elementary functions to add. The 'Floating'
-class can be used as reference.
-
-Another useful addition would be decent 'Show' and 'Read' instances.
-The 'show' implementation could output the numerical value and the
-unit expressed in (base?) SI units, along the lines of:
-
-] instance (Fractional a, Show a) => Show (Length a)
-]   where show x = show (x /~ meter) ++ " m"
-
-Additional functions could be provided for "showing" with any unit
-and prefix.  The 'read' implementation should be able to read values
-with any unit and prefix. It is not clear to the author how to best
-implement these.
-
-Additional physics models could be implemented. See [3] for ideas.
-
-
-= Related work =
-
-Henning Thielemann numeric prelude has a physical units library,
-however, checking of dimensions is dynamic rather than static.
-Aaron Denney has created a toy example of statically checked
-physical dimensions covering only length and time. HaskellWiki
-has pointers [4] to these.
-
-Also see Samuel Hoffstaetter's blog post [5] which uses techniques
-similar to this library.
-
-Libraries with similar functionality exist for other programming
-languages and may serve as inspiration. The author has found the
-Java library JScience [6] and the Fortress programming language [7]
-particularly noteworthy.
-
-
-= References =
-
-[1] http://physics.nist.gov/Pubs/SP811/
-[2] http://en.wikipedia.org/wiki/Escape_velocity
-[3] http://jscience.org/api/org/jscience/physics/models/package-summary.html
-[4] http://www.haskell.org/haskellwiki/Physical_units
-[5] http://liftm.wordpress.com/2007/06/03/scientificdimension-type-arithmetic-and-physical-units-in-haskell/
-[6] http://jscience.org/
-[7] http://research.sun.com/projects/plrg/fortress.pdf
-
diff --git a/Numeric/Units/Dimensional/CGS.lhs b/Numeric/Units/Dimensional/CGS.lhs
deleted file mode 100644
--- a/Numeric/Units/Dimensional/CGS.lhs
+++ /dev/null
@@ -1,339 +0,0 @@
-Numeric.Dimensional.CGS -- CGS system of units
-Bjorn Buckwalter, bjorn.buckwalter@gmail.com
-License: BSD3
-
-!!! EXPERIMENTAL !!!
-
-
-= Introduction =
-
-This module was prompted by an email from Chuck Blake[1]. He asked if
-the Dimensional library could support other systems of units than
-SI, in particular systems such as the centimeter-gram-second (CGS)
-system where fractional exponents of dimensions occur. He also
-wondered whether it was possible to convert quantities between
-different systems while statically ensuring that a given conversion
-was valid.
-
-In this module we show that we can in a straight forward manner
-support systems with rational exponents, provided that the rationals
-that may be encountered are known a priori. As an example we provide
-a rudimentary implementation of the CGS system.
-
-We also show that we can indeed statically prohibit invalid conversions
-between different systems.
-
-
-= Caveats =
-
-I'm ignorantly assuming that when working with the CGS (or MKS)
-system you will only (meaningfully?) encounter half-exponents and
-only of the length and mass dimensions. Of course, in other systems
-other rational exponents may be encountered.
-
-I am also assuming that the CGS system would not be employed when
-working with temperature, amount or luminosity. This is evident in
-the below type signatures where I have assumed zero extent in the
-temperature, amount and luminosity dimensions. If this is incorrect
-I would appreciate pointers to the CGS representation of these
-dimensions.
-
-Please correct and inform me if my assumptions are wrong!
-
-
-= Preliminaries =
-
-> {-# LANGUAGE UndecidableInstances
->            , ScopedTypeVariables
->            , EmptyDataDecls
->            , MultiParamTypeClasses
->            , FlexibleInstances
->            , FlexibleContexts
-> #-}
-> {-# OPTIONS_GHC -fcontext-stack=30 #-}
-> {- |
->    Copyright  : Copyright (C) 2006-2013 Bjorn Buckwalter
->    License    : BSD3
->
->    Maintainer : bjorn.buckwalter@gmail.com
->    Stability  : Experimental
->    Portability: GHC only?
->
-> Please refer to the literate Haskell code for documentation of both API
-> and implementation.
-> -}
-
-> module Numeric.Units.Dimensional.CGS where
-
-> import Prelude
->   ( undefined, Num, Fractional, Floating, Show, recip, Double, unwords, (.) )
-> import qualified Prelude
-> import Numeric.Units.Dimensional hiding ( DLength, DMass, DTime, DElectricCurrent )
-> import Numeric.Units.Dimensional.Quantities as SIQ
-> import qualified Numeric.Units.Dimensional.SIUnits as SI
-> import qualified Numeric.NumType as N
-> import Numeric.NumType ( Neg2, Neg1, Zero, Pos1, Pos2, Pos3, NumType )
-> import Numeric.NumType ( neg2, pos2, pos3 )
-> import Data.Maybe (catMaybes)
-
-
-= Dimensions =
-
-Analogously with the SI we collect the base dimensions of the CGS
-system in the data type 'CGSDim'.
-
-> data CGSDim lh mh t
-
-In the above 'lh' and 'mh' represent the number of half-exponents
-of length and mass respectively while 't' represents the number of
-whole-exponents. The base dimensions illustrate this.
-
-> type DLength = CGSDim Pos2 Zero Zero
-> type DMass   = CGSDim Zero Pos2 Zero
-> type DTime   = CGSDim Zero Zero Pos1
-
-We add a few non-base dimensions for the sake of example. Charge
-is particularly interesting as it illustrates the need for
-half-exponents as described in [2].
-
-> type DElectricCurrent = CGSDim Pos3 Pos1 Neg2
-> type DCharge = CGSDim Pos3 Pos1 Neg1
-
-
-= 'Mul', 'Div', 'Pow' and 'Root' instances =
-
-The 'Mul', 'Div', 'Pow' and 'Root' instances are strictly analogous
-with the SI.
-
-> instance ( N.Sum lh lh' lh''
->          , N.Sum mh mh' mh''
->          , N.Sum t  t'  t'' ) => Mul (CGSDim lh   mh   t)
->                                      (CGSDim lh'  mh'  t')
->                                      (CGSDim lh'' mh'' t'')
-
-> instance ( N.Sum lh lh' lh''
->          , N.Sum mh mh' mh''
->          , N.Sum t  t'  t'' ) => Div (CGSDim lh'' mh'' t'')
->                                      (CGSDim lh'  mh'  t')
->                                      (CGSDim lh   mh   t)
-
-> instance ( N.Mul lh x lh'
->          , N.Mul mh x mh'
->          , N.Mul t  x t' ) => Pow (CGSDim lh  mh  t) x
->                                   (CGSDim lh' mh' t')
-
-> instance ( N.Div lh x lh'
->          , N.Div mh x mh'
->          , N.Div t  x t' ) => Root (CGSDim lh  mh  t) x
->                                    (CGSDim lh' mh' t')
-
-
-= Units =
-
-We define the base units of the system. By defining 'meter' with a
-"scale" of 100 we get a scale of one for 'centi meter'.
-
-> meter  :: Num a => Unit DLength a
-> meter  = Dimensional 100
-> gram   :: Num a => Unit DMass a
-> gram   = Dimensional 1
-> second :: Num a => Unit DTime a
-> second = Dimensional 1
-
-We continue by defining the CGS equivalents of the other base SI
-units. Actually we limit ourselves to 'ampere' since I am not sure
-if or how the SI base dimensions other than current are expressed
-in CGS.
-
-> ampere :: Floating a => Unit DElectricCurrent a
-> ampere = prefix (recip 3.33564e-10) ((SI.centi meter ^ pos3) ^/ pos2 * gram ^/ pos2 * second ^ neg2)
-
-We also define the preferred CGS unit for charge.
-
-> franklin :: Floating a => Unit DCharge a -- Also known as "esu".
-> franklin = gram ^/ pos2 * (SI.centi meter ^ pos3) ^/ pos2 / second
-
-
-= Conversion from SI =
-
-At some point we may wish to convert an SI quantity to a CGS quantity
-or vice versa.
-
-In order to convert a 'Quantity' from the SI system to the CGS
-system we use the strategy of dividing the quantity by the SI base
-unit and multiplying the resulting number (sans dimension) by the
-equivalent CGS unit. To realize this strategy we must be able to
-obtain the SI base unit and the equivalent CGS unit for a given
-quantity. We start with the SI unit since it is trivial.
-
-> unit_SI :: Num a => Quantity (Dim l m t i th n j) a -> Unit (Dim l m t i th n j) a
-> unit_SI _ = Dimensional 1
-
-(Perhaps the above function would be better defined in another
-module.)
-
-Obtaining the CGS unit corresponding to the SI base unit of a
-Quantity isn't quite as trivial. The function body itself is
-straight-forward enough, the hairy part is the type signature.
-
-> unit_CGS :: forall a l m t i l2 m2 il it l' m' t'.
->          ( Floating a
->          , N.Mul Zero l Zero, N.Mul Pos2 l l2
->          , N.Mul Zero m Zero, N.Mul Pos2 m m2
->          , N.Mul Zero t Zero, N.Mul Pos1 t t
->          , N.Sum l2 Zero l2
->          , N.Sum Zero m2 m2,  N.Sum m2 Zero m2
->          , N.Sum Zero t  t
->          , N.Mul Pos3 i  il
->          , N.Mul Pos1 i  i
->          , N.Mul Neg2 i  it
->          , N.Sum l2 il l'
->          , N.Sum m2 i  m'
->          , N.Sum t  it t'
->          ) => Quantity (Dim l m t i Zero Zero Zero) a -> Unit (CGSDim l' m' t') a
-> unit_CGS _ = meter        ^ (undefined :: l)
->            * SI.kilo gram ^ (undefined :: m)
->            * second       ^ (undefined :: t)
->            * ampere       ^ (undefined :: i)
-
-Note that since the base dimensions of the CGS are a subset of those
-of the SI the mapping of types from SI to CGS is unambiguous.
-
-Also note that complex as the type signature may be producing it is a
-mostly mechanical process.
-
-With the above two functions we can define the function that converts
-a unit from the SI. We omit the type signature since it is hairy
-but can be readily inferred.
-
-> fromSI x = x /~ unit_SI  x *~ unit_CGS x
-
-
-= Conversion to SI =
-
-We use the same strategy to convert from CGS to SI. However, when
-converting from CGS to SI there may be several valid SI dimensionalities
-for any given CGS dimensionality. We will handle this ambiguity by
-requiring the user to specify the desired type (except when it is
-inferable) of the resulting quantity.  For example:
-
-] toSI (3.2 *~ centi meter) :: Length Double
-
-In order to do this we must employ lexically scoped type variables
-and provide the hairy type signature for the 'toSI' function.
-
-> toSI :: forall a l m t i l2 m2 il it l' m' t'.
->          ( Floating a
->          , N.Mul Zero l Zero, N.Mul Pos2 l l2
->          , N.Mul Zero m Zero, N.Mul Pos2 m m2
->          , N.Mul Zero t Zero, N.Mul Pos1 t t
->          , N.Sum l2 Zero l2
->          , N.Sum Zero m2 m2,  N.Sum m2 Zero m2
->          , N.Sum Zero t  t
->          , N.Mul Pos3 i  il
->          , N.Mul Pos1 i  i
->          , N.Mul Neg2 i  it
->          , N.Sum l2 il l'
->          , N.Sum m2 i  m'
->          , N.Sum t  it t'
->          ) => Quantity (CGSDim l' m' t') a -> Quantity (Dim l m t i Zero Zero Zero) a
-> toSI x = x /~ unit_CGS (undefined :: Quantity (Dim l m t i Zero Zero Zero) a)
->            *~ unit_SI  (undefined :: Quantity (Dim l m t i Zero Zero Zero) a)
-
-Again, the type signature is complex but deriving it is a mechanical
-process.
-
-
-= 'Show' instance =
-
-We round off by writing 'Show' instance for 'CGSDim' analogous to
-that of 'Dim'.
-
-Out of laziness we use the notation "sqrt(cm)" to represent halves
-of integral dimensions. Nothing is technically keeping us from doing
-a better job here.
-
-> instance forall lh mh t.
->     ( NumType lh
->     , NumType mh
->     , NumType t
->     ) => Show (CGSDim lh mh t) where
->     show _ = (unwords . catMaybes)
->              [ dimUnit "sqrt(cm)" (undefined :: lh)
->              , dimUnit "sqrt(g)"  (undefined :: mh)
->              , dimUnit "s"        (undefined :: t)
->              ]
-
-
-= Examples =
-
-Let us try the Coulomb attraction example from [2]. We start by
-performing the calculation in the SI.
-
-> q_si  = 1.6021773e-19 *~ SI.coulomb -- Elementary charge in SI.
-> r_si  = 0.1 *~ SI.nano SI.meter     -- Distance in SI
-> f_si  = q_si ^ pos2 / (_4 * pi * e0 * r_si ^ pos2)
->   where
->       e0 = 8.8541878e-12 *~ (SI.ampere * SI.second / (SI.volt * SI.meter))
-
-The same calculation in the CGS system.
-
-> q_cgs = fromSI q_si -- Elementary charge in CGS.
-> r_cgs = fromSI r_si -- Distance in CGS
-> f_cgs = q_cgs ^ pos2 / r_cgs ^ pos2
-
-Inspecting the values in GHCi shows us that the results are consistent
-(within reasonable accuracy) with [2].
-
-  *Numeric.Dimensional.CGS> f_si
-  2.3070794737101255e-8 m kg s^-2
-  *Numeric.Dimensional.CGS> f_cgs
-  2.30708078598602e-3 sqrt(cm)^2 sqrt(g)^2 s^-2
-
-To convert from CGS to SI we must specify the type of the SI 'Quantity'.
-
-> f_si' = toSI f_cgs :: SIQ.Force Double
-
-  *Numeric.Dimensional.CGS> f_si'
-  2.3070807859860202e-8 m kg s^-2
-
-We follow up with another conversion example demonstrating the
-ambiguity in the conversion from CGS to SI.
-
-> c     = 1 *~ SI.farad -- A SI capacitance.
-> c_cgs = fromSI c      -- Capacitance has dimensionality L in CGS.
-> c'    = toSI c_cgs :: SIQ.Capacitance Double
-> c''   = toSI c_cgs :: Length Double
-
-  *Numeric.Dimensional.CGS> c
-  1.0 m^-2 kg^-1 s^4 A^2
-  *Numeric.Dimensional.CGS> c_cgs
-  8.98755691740885e11 sqrt(cm)^2
-  *Numeric.Dimensional.CGS> c'
-  1.0 m^-2 kg^-1 s^4 A^2
-  *Numeric.Dimensional.CGS> c''
-  8.98755691740885e9 m
-
-
-= Future work =
-
-This is a very rudimentary implementation. To make it more practical
-a significant number of quantities and units, in particularly those
-commonly used with the CGS, would need to be added. In the mean
-time all units defined for the SI can be used with the CGS by
-applying 'fromSI' to quantities defined from the SI units.
-
-If anyone is willing to add quantities/units (or other enhancements)
-I will happily to accept patches. Personally I do not expect to use
-this module and therefore do not intend to invest much more time
-in it. If the module has other users I might reconsider.
-
-And of course, another direction of future work is to define
-additional systems (e.g. natural, relativistic) using this module
-as a template. I imagine this should be fairly straight forward.
-
-
-= References =
-
-[1] http://code.google.com/p/dimensional/wiki/ChuckBlake20070611
-[2] http://www.tf.uni-kiel.de/matwis/amat/mw1_ge/kap_2/basics/b2_1_14.html
diff --git a/Numeric/Units/Dimensional/Extensible.lhs b/Numeric/Units/Dimensional/Extensible.lhs
deleted file mode 100644
--- a/Numeric/Units/Dimensional/Extensible.lhs
+++ /dev/null
@@ -1,187 +0,0 @@
-Numeric.Dimensional.Extensible -- Extensible physical dimensions
-Bjorn Buckwalter, bjorn.buckwalter@gmail.com
-License: BSD3
-
-
-= Summary =
-
-On January 3 Mike Gunter asked[1]:
-
-  The very nice Buckwalter and Denney dimensional-numbers packages
-  both work on a fixed set of base dimensions.  This is a significant
-  restriction for me--I want to avoid adding apples to oranges as
-  well as avoiding adding meters to grams.  Is it possible to have
-  an extensible set of base dimensions?  If so, how usable can such
-  a system be made?  Is it very much worse than a system with a fixed
-  set of base dimensions?
-
-In this module we facilitate the addition an arbitrary number of
-"extra" dimensions to the seven base dimensions defined in
-'Numeric.Dimensional'. A quantity or unit with one or more extra
-dimensions will be referred to as an "extended Dimensional".
-
-
-= Preliminaries =
-
-Similarly with 'Numeric.Dimensional' this module requires GHC
-6.6 or later.
-
-> {-# LANGUAGE UndecidableInstances
->            , ScopedTypeVariables
->            , EmptyDataDecls
->            , MultiParamTypeClasses
->            , FunctionalDependencies
->            , FlexibleInstances
-> #-}
-
-> {- |
->    Copyright  : Copyright (C) 2006-2013 Bjorn Buckwalter
->    License    : BSD3
->
->    Maintainer : bjorn.buckwalter@gmail.com
->    Stability  : Experimental
->    Portability: GHC only?
->
-> Please refer to the literate Haskell code for documentation of both API
-> and implementation.
-> -}
-
-> module Numeric.Units.Dimensional.Extensible ( DExt, showDExt ) where
-
-> import Numeric.Units.Dimensional ( Dim, Mul, Div, Pow, Root, dimUnit )
-> import Numeric.NumType ( NumType, Sum, Negate, Zero, Pos, Neg )
-> import qualified Numeric.NumType as N ( Div, Mul )
-
-
-= 'DExt', 'Apples' and 'Oranges' =
-
-We define the datatype 'DExt' which we will use to increase the
-number of dimensions from the seven SI base dimensions to an arbitrary
-number of dimensions.
-
-> data DExt a n d
-
-The type variable 'a' is used to tag the extended dimensions with
-an identity, thus preventing inadvertent mixing of extended dimensions.
-
-Using 'DExt' we can define type synonyms for extended dimensions
-applicable to our problem domain. For example, Mike Gunter could
-define the 'Apples' and 'Oranges' dimensions and the corresponding
-quantities.
-
-] data TApples -- Type tag.
-] type DApples  = DExt TApples Pos1 DOne
-] type Apples   = Quantity DApples
-
-] data TOrange -- Type tag.
-] type DOranges = DExt TApples Zero (DExt TOranges Pos1 DOne)
-] type Oranges  = Quantity DOranges
-
-And while he was at it he could define corresponding units.
-
-] apple  :: Num a => Unit DApples a
-] apple  = Dimensional 1
-] orange :: Num a => Unit DOranges a
-] orange = Dimensional 1
-
-When extending dimensions we adopt the convention that the first
-(outermost) dimension is the reference for aligning dimensions, as
-shown in the above example. This is important when performing
-operations on two Dimensionals with a differing number of extended
-dimensions.
-
-
-= 'Show' helper function =
-
-We provide a helper function to ease defining 'Show' instances.
-
-> showDExt :: forall a n d. (NumType n, Show d) => String -> DExt a n d -> String
-> showDExt u _ = showHelp (dimUnit u (undefined :: n)) (show (undefined :: d))
->        where
->            showHelp Nothing   s  = s
->            showHelp (Just u') "" = u'
->            showHelp (Just u') s  = u' ++ " " ++ s
-
-Using this helper function defining 'Show' instances for the dimensions
-with extent in apples and oranges is simple.
-
-] instance (NumType n, Show d) => Show (DExt TApples n d) where
-]   show = showDExt "apple"
-] instance (NumType n, Show d) => Show (DExt TOranges n d) where
-]   show = showDExt "orange"
-
-
-= The 'DropZero' class =
-
-The choice of convention may seem backwards considering the opposite
-convention is used for NumTypes (though for NumTypes the distinction
-is arguably irrelevant). However, this choice facilitates relatively
-simple interoperability with base dimensions. In particular it lets
-us drop any dimensions with zero extent adjacent to the terminating
-'Dim'. To capture this property we define the 'DropZero' class.
-
-> class DropZero d d' | d -> d'
-
-The following 'DropZero' instances say that when an extended dimension
-with zero extent is next to a 'Dim' the extended dimension can be
-dropped. In all other cases the dimensions are retained as is.
-
-> instance DropZero (DExt a Zero (Dim l m t i th n j)) (Dim l m t i th j j)
-> instance DropZero (DExt a Zero (DExt a' n d)) (DExt a Zero (DExt a' n d))
-> instance DropZero (DExt a (Pos n) d) (DExt a (Pos n) d)
-> instance DropZero (DExt a (Neg n) d) (DExt a (Neg n) d)
-
-
-= Classes from 'Numeric.Dimensional' =
-
-We get negation, addition and subtraction for free with extended
-Dimensionals. However, we will need instances of the 'Mul', 'Div',
-'Pow' and 'Root' classes for the corresponding operations to work.
-
-Multiplication and division can cause dimensions to be eliminated.
-We use the 'DropZero' type class to guarantee that the result of a
-multiplication or division has a minimal representation.
-
-When only one of the 'Mul' factors is an extended dimensional there is
-no need to minimize.
-
-> instance (Mul d (Dim l m t i th n j) d')
->       => Mul (DExt a x d) (Dim l m t i th n j) (DExt a x d')
-> instance (Mul (Dim l m t i th n j) d d')
->       => Mul (Dim l m t i th n j) (DExt a x d) (DExt a x d')
-
-If both of the factors are extended the product must be minimized.
-
-> instance (Sum n n' n'', Mul d d' d'', DropZero (DExt a n'' d'') d''')
->       => Mul (DExt a n d) (DExt a n' d') d'''
-
-Analogously for 'Div'.
-
-> instance (Div d (Dim l m t i th n j) d')
->       => Div (DExt a x d) (Dim l m t i th n j) (DExt a x d')
-> instance (Div (Dim l m t i th n j) d d', Negate x x')
->       => Div (Dim l m t i th n j) (DExt a x d) (DExt a x' d')
-
-> instance (Sum n'' n' n, Div d d' d'', DropZero (DExt a n'' d'') d''')
->       => Div (DExt a n d) (DExt a n' d') d'''
-
-The instances for 'Pow' and 'Root' are simpler since they can not
-change any previously non-zero to be eliminated.
-
-> instance (N.Mul n x n', Pow d x d')   => Pow  (DExt a n d) x (DExt a n' d')
-> instance (N.Div n x n', Root  d x d') => Root (DExt a n d) x (DExt a n' d')
-
-
-= Note =
-
-The use of 'DExt' is not particularily modular. Exrended dimensions
-must adhere to a strict ordering in order to be compatible in terms
-of e.g. multiplication. This makes it difficult to add extra
-dimensions without full knowledge of all extra dimension one will
-be interacting with.
-
-
-= References =
-
-[1] http://www.haskell.org/pipermail/haskell-cafe/2007-January/021069.html
-
diff --git a/Numeric/Units/Dimensional/ExtensibleTest.lhs b/Numeric/Units/Dimensional/ExtensibleTest.lhs
deleted file mode 100644
--- a/Numeric/Units/Dimensional/ExtensibleTest.lhs
+++ /dev/null
@@ -1,91 +0,0 @@
-> {-# LANGUAGE EmptyDataDecls, FlexibleInstances #-}
-
-> module Numeric.Units.Dimensional.ExtensibleTest where
-
-> import Numeric.Units.Dimensional.Prelude
-> import Numeric.Units.Dimensional.Extensible
-> import Numeric.Units.Dimensional ( Dimensional (Dimensional), dimUnit )
-> import Numeric.NumType ( NumType, Zero, Pos1, Neg1 )
-> import Test.HUnit
-> import qualified Prelude
-
-
-= Setting up the problem domain =
-
-For testing we will use apples, oranges and peaches. We define the
-type tags and show instances for each.
-
-> data TApples  -- Type tag.
-> type DApples  = DExt TApples Pos1 DOne
-> type Apples   = Quantity DApples
-
-> data TOranges -- Type tag.
-> type DOranges = DExt TApples Zero (DExt TOranges Pos1 DOne)
-> type Oranges  = Quantity DOranges
-
-> data TPeaches -- Type tag.
-> type DPeaches = DExt TApples Zero (DExt TOranges Zero (DExt TPeaches Pos1 DOne))
-> type Peaches  = Quantity DPeaches
-
-Define show instances.
-
-> instance (NumType n, Show d) => Show (DExt TApples n d) where
->   show = showDExt "apple"
-
-> instance (NumType n, Show d) => Show (DExt TOranges n d) where
->   show = showDExt "orange"
-
-> instance (NumType n, Show d) => Show (DExt TPeaches n d) where
->   show = showDExt "peaches"
-
-Finally the base units.
-
-> apple  :: Num a => Unit DApples a
-> apple  = Dimensional 1
-> orange :: Num a => Unit DOranges a
-> orange = Dimensional 1
-> peach  :: Num a => Unit DPeaches a
-> peach  = Dimensional 1
-
-
-= Test values =
-
-> a = 1 *~ apple
-> o = 2 *~ orange
-> m = 3 *~ meter
-> p = 4 *~ peach
-
-
-= Stuff we expect to compile =
-
-> f = a / o * p
-> f' = a * o
-> f'' = m / a
-
-> foo1 :: Quantity (DExt TApples Pos1 (DExt TOranges Neg1 (DLength))) Double
-> foo1 = a / o * m
-
-> foo2 :: Double
-> foo2 = a * m / a /~ meter
-
-> foo3 :: Length Double
-> foo3 = a * m / a + m
-
-
-Finally a HUnit test case.
-
-> testShow = TestLabel "Test 'Show' instance" $ TestList
->   [ TestCase $ show (1 *~ apple) @?= "1 apple"
->   , TestCase $ show (2 *~ orange) @?= "2 orange"
->   , TestCase $ show (2.0 *~ (apple / second)) @?= "2.0 apple s^-1"
->   , TestCase $ show (2.0 *~ (meter ^ pos2 / peach ^ pos2)) @?= "2.0 peaches^-2 m^2"
->   , TestCase $ show (2.0 *~ (apple ^ pos2 / peach ^ pos2)) @?= "2.0 apple^2 peaches^-2"
->   , TestCase $ show (undefined :: DApples) @?= "apple"
->   ]
-
-Main function.
-
-> main = do
->   putStrLn "If I compiled I'm mostly OK!"
->   runTestTT $ TestList [testShow]
-
diff --git a/Numeric/Units/Dimensional/NonSI.lhs b/Numeric/Units/Dimensional/NonSI.lhs
deleted file mode 100644
--- a/Numeric/Units/Dimensional/NonSI.lhs
+++ /dev/null
@@ -1,194 +0,0 @@
-Numeric.Dimensional.NonSI
-Bjorn Buckwalter, bjorn.buckwalter@gmail.com
-License: BSD3
-
-
-= Summary =
-
-This module defines units that are not part of the SI, with the
-exception of those defined in the 'SIUnits' module (units outside
-of the SI accepted for use with the SI).
-
-Any chapters, sections or tables referenced are from [1] unless
-otherwise specified.
-
-> {- |
->    Copyright  : Copyright (C) 2006-2013 Bjorn Buckwalter
->    License    : BSD3
->
->    Maintainer : bjorn.buckwalter@gmail.com
->    Stability  : Stable
->    Portability: GHC only?
->
-> Please refer to the literate Haskell code for documentation of both API
-> and implementation.
-> -}
-
-> module Numeric.Units.Dimensional.NonSI where
-
-> import Numeric.Units.Dimensional.Prelude
-> import qualified Prelude
-
-
-= Neper, bel, shannon and the like =
-
-The units of section 5.1.2 are purposefully (but not permanently)
-omitted. In fact the logarithmic units (see section 8.7) are
-problematic and it is not clear how to implement them. Perhaps with
-a conversion function similar to for degrees Celsius.
-
-
-= Table 7 =
-
-"Units accepted for use with the SI whose values in SI units are
-obtained experimentally."
-
-When [1] was published The electronvolt had a standard combined
-uncertainity of 0.00000049e-19 J and the unified atomic mass unit
-had a combined uncertainty of 0.0000010e-27 kg.
-
-> electronVolt :: Fractional a => Unit DEnergy a
-> electronVolt = prefix 1.60217733e-19 joule
-> unifiedAtomicMassUnit :: Fractional a => Unit DMass a
-> unifiedAtomicMassUnit = prefix 1.6605402e-27 (kilo gram)
-
-
-= Standard gravity =
-
-In order to relate e.g. pounds mass to pounds force we define the unit
-'gee' equal to the standard gravity g_0: the nominal acceleration of a
-body in free fall in a vacuum near the surface of the earth (note that
-local values of acceleration due to gravity will differ from the standard
-gravity). I.e. g_0 = 1 gee.
-
-> gee :: Fractional a => Unit DAcceleration a
-> gee = prefix 9.80665 meter / second ^ pos2
-
-
-= Inch-pound units =
-
-Some US customary (that is, inch-pound) units.
-
-> inch, foot, mil :: Fractional a => Unit DLength a
-> inch = prefix 2.54 (centi meter)
-> foot = prefix 12 inch     -- 0.3048 m
-> mil  = prefix 0.001 inch
-> poundMass, ounce :: Fractional a => Unit DMass a
-> poundMass = prefix 0.45359237 (kilo gram)
-> ounce     = prefix (1 Prelude./ 16) poundMass
-
-> poundForce :: Fractional a => Unit DForce a
-> poundForce = poundMass * gee  -- 4.4482 N
-
-Pounds of force per square inch.
-
-> psi :: Fractional a => Unit DPressure a
-> psi = poundForce / inch ^ pos2
-
-
-= Various other (non inch-pound) units =
-
-> yard, mile, nauticalMile :: (Fractional a) => Unit DLength a
-> yard = prefix 3 foot
-> mile = prefix 1760 yard
-> nauticalMile = prefix 1852 meter
-> revolution :: (Floating a) => Unit DOne a
-> revolution = prefix (2 Prelude.* Prelude.pi) radian
-> solid :: (Floating a) => Unit DOne a
-> solid = prefix (4 Prelude.* Prelude.pi) steradian
-> teaspoon :: (Fractional a) => Unit DVolume a
-> teaspoon = prefix 5 (milli liter)
-
-The IAU recommends[2] that:
-
-  Although there are several different kinds of year (as there are
-  several kinds of day), it is best to regard a year as a julian
-  year of 365.25 days (31.5576 Ms) unless otherwise specified.
-
-This aligns well with my needs so I'm happy to oblige. We define
-the year in terms of seconds in order to avoid a 'Fractional'
-constraint, and also provide a Julian century.
-
-> year, century :: Num a => Unit DTime a
-> year    = prefix 31557600 second
-> century = prefix 100 year
-
-
-= Pressure units =
-
-Psi was defined earlier.
-
-> bar :: (Fractional a) => Unit DPressure a
-> bar = prefix 1.0e5 pascal
-
-From Wikipedia[3]:
-
-  The standard atmosphere (atm) is an established constant. It is
-  approximately equal to typical air pressure at earth mean sea
-  level.
-
-> atmosphere :: (Fractional a) => Unit DPressure a
-> atmosphere = prefix 101325 pascal
-
-From Wikipedia:
-
-  A technical atmosphere (symbol: at) is a non-SI unit of pressure equal
-  to one kilogram-force per square centimeter.
-
-> technicalAtmosphere :: (Fractional a) => Unit DPressure a
-> technicalAtmosphere = kilo gram * gee * centi meter ^ neg2
-
-Manometric pressure units:
-
-Per Wikipedia[4] one mmHg (millimeter of mercury) is defined as:
-
-  The pressure exerted at the base of a column of fluid exactly 1 mm high,
-  when the density of the fluid is exactly 13.5951 g/cm^3, at a place
-  where the acceleration of gravity is exactly 9.80665 m/s^2.
-
-The chosen fluid density approximately corresponds to that of mercury
-at 0 deg. Under most conditions, 1 mmHg is approximately equal to 1 torr.
-
-> mmHg :: (Fractional a) => Unit DPressure a
-> mmHg = prefix 13.5951 gram * centi meter ^ neg3 * milli meter * gee
-
-One torr (symbol: Torr) is defined as 1/760 atm, which is approximately equal
-to 1 mmHg.
-
-> torr :: (Fractional a) => Unit DPressure a
-> torr = prefix (1 Prelude./ 760) atmosphere
-
-
-= Radiation =
-
-> rad :: (Fractional a) => Unit DAbsorbedDose a
-> rad = centi gray
-
-
-= Kinematic Viscosity =
-
-> stokes :: (Fractional a) => Unit DKinematicViscosity a
-> stokes = centi meter ^ pos2 / second
-
-
-= Imperial Volumes =
-
-Per http://en.wikipedia.org/wiki/Imperial_units.
-
-> imperialGallon, imperialQuart, imperialPint, imperialCup,
->                 imperialGill, imperialFluidOunce
->                 :: (Fractional a) => Unit DVolume a
-> imperialGallon = prefix 4.54609 liter
-> imperialQuart  = prefix (1 Prelude./ 4) imperialGallon
-> imperialPint   = prefix (1 Prelude./ 8) imperialGallon
-> imperialCup    = prefix 0.5 imperialPint
-> imperialGill   = prefix (1 Prelude./ 4) imperialPint
-> imperialFluidOunce = prefix (1 Prelude./ 20) imperialPint
-
-
-= References =
-
-[1] http://physics.nist.gov/Pubs/SP811/
-[2] http://www.iau.org/science/publications/proceedings_rules/units/
-[3] http://en.m.wikipedia.org/wiki/Pressure
-[4] http://en.m.wikipedia.org/wiki/Torr
diff --git a/Numeric/Units/Dimensional/Prelude.hs b/Numeric/Units/Dimensional/Prelude.hs
deleted file mode 100644
--- a/Numeric/Units/Dimensional/Prelude.hs
+++ /dev/null
@@ -1,27 +0,0 @@
-module Numeric.Units.Dimensional.Prelude
-    ( module Numeric.Units.Dimensional
-    , module Numeric.Units.Dimensional.Quantities
-    , module Numeric.Units.Dimensional.SIUnits
-    , module Numeric.NumType
-    , module Prelude
-    ) where
-
-import Numeric.Units.Dimensional hiding
-    ( Dimensional (Dimensional)
-    )
-
-import Numeric.Units.Dimensional.Quantities
-
-import Numeric.Units.Dimensional.SIUnits
-
-import Numeric.NumType
-    ( neg5, neg4, neg3, neg2, neg1, zero, pos1, pos2, pos3, pos4, pos5
-    )  -- Used in exponents.
-
-import Prelude hiding
-    ( (+), (-), (*), (/), (^), (**)
-    , abs, negate, pi, exp, log, sqrt
-    , sin, cos, tan, asin, acos, atan, atan2
-    , sinh, cosh, tanh, asinh, acosh, atanh
-    , sum
-    )  -- Hide definitions overridden by 'Numeric.Dimensional'.
diff --git a/Numeric/Units/Dimensional/Quantities.lhs b/Numeric/Units/Dimensional/Quantities.lhs
deleted file mode 100644
--- a/Numeric/Units/Dimensional/Quantities.lhs
+++ /dev/null
@@ -1,332 +0,0 @@
-Numeric.Dimensional.Quantities
-Bjorn Buckwalter, bjorn@buckwalter.se
-License: BSD3
-
-
-= Summary =
-
-This module defines type synonyms for common dimensionalities and
-the associated quantity types. Additional dimensionalities and
-quantity types will be added on an as-needed basis.
-
-The definitions in this module are grouped so that a type synonym
-for the dimensionality is defined first in terms of base dimension
-exponents. Then a type synonym for the corresponding quantity type
-is defined. If there are several quantity types with the same
-dimensionality type synonyms are provided for each quantity type.
-
-> {- |
->    Copyright  : Copyright (C) 2006-2014 Bjorn Buckwalter
->    License    : BSD3
->
->    Maintainer : bjorn@buckwalter.se
->    Stability  : Stable
->    Portability: GHC only?
->
-> Please refer to the literate Haskell code for documentation of both API
-> and implementation.
-> -}
-
-> module Numeric.Units.Dimensional.Quantities where
-
-> import Numeric.Units.Dimensional
->   ( Dim, Quantity, Dimensionless
->   , DOne, DLuminousIntensity, DThermodynamicTemperature
->   , Unit, DLength, (^+) -- Used only for 'square' and 'cubic'.
->   )
-> import Numeric.NumType
->   ( Neg3, Neg2, Neg1, Zero, Pos1, Pos2, Pos3, Pos4
->   , pos2, pos3 -- Used only for 'square' and 'cubic'.
->   )
-
-
-= Quantities from [1] =
-
-The following quantities are all from the NIST publication "Guide
-for the Use of the International System of Units (SI)" [1]. Any
-chapters, sections or tables referenced are from [1] unless otherwise
-specified.
-
-For lack of better organization we provide definitions grouped by
-table in [1].
-
-
-== Table 2 ==
-
-"Examples of SI derived units expressed in terms of SI base units."
-
-> type DArea = Dim Pos2 Zero Zero Zero Zero Zero Zero
-> type Area  = Quantity DArea
-
-> type DVolume = Dim Pos3 Zero Zero Zero Zero Zero Zero
-> type Volume  = Quantity DVolume
-
-> type DVelocity = Dim Pos1 Zero Neg1 Zero Zero Zero Zero
-> type Velocity  = Quantity DVelocity
-
-> type DAcceleration = Dim Pos1 Zero Neg2 Zero Zero Zero Zero
-> type Acceleration  = Quantity DAcceleration
-
-> type DWaveNumber = Dim Neg1 Zero Zero Zero Zero Zero Zero
-> type WaveNumber  = Quantity DWaveNumber
-
-> type DMassDensity = Dim Neg3 Pos1 Zero Zero Zero Zero Zero
-> type MassDensity  = Quantity DMassDensity
-> type Density      = MassDensity -- Short name.
-
-> type DSpecificVolume = Dim Pos3 Neg1 Zero Zero Zero Zero Zero
-> type SpecificVolume  = Quantity DSpecificVolume
-
-> type DCurrentDensity = Dim Neg2 Zero Zero Pos1 Zero Zero Zero
-> type CurrentDensity  = Quantity DCurrentDensity
-
-> type DMagneticFieldStrength = Dim Neg1 Zero Zero Pos1 Zero Zero Zero
-> type MagneticFieldStrength  = Quantity DMagneticFieldStrength
-
-> type DAmountOfSubstanceConcentration = Dim Neg3 Zero Zero Zero Zero Pos1 Zero
-> type AmountOfSubstanceConcentration  = Quantity DAmountOfSubstanceConcentration
-> type Concentration                   = AmountOfSubstanceConcentration -- Short name.
-
-> type DLuminance = Dim Neg2 Zero Zero Zero Zero Zero Pos1
-> type Luminance  = Quantity DLuminance
-
-=== Powers of length units ===
-
-It is permissible to express powers of length units by prefixing
-'square' and 'cubic' (see section 9.6 "Spelling unit names raised
-to powers" of [1]).
-
-> square :: (Num a) => Unit DLength a -> Unit DArea a
-> square x = x ^+ pos2
-> cubic  :: (Num a) => Unit DLength a -> Unit DVolume a
-> cubic  x = x ^+ pos3
-
-These definitions may seem slightly out of place but these is no
-obvious place where they should be. Here they are at least close
-to the definitions of 'DLength' and 'DVolume'.
-
-
-== Table 3a ==
-
-"SI derived units with special names and symbols, including the
-radian and steradian."
-
-> type DPlaneAngle = DOne
-> type PlaneAngle  = Dimensionless
-
-> type DSolidAngle = DOne
-> type SolidAngle  = Dimensionless
-
-> type DFrequency = Dim Zero Zero Neg1 Zero Zero Zero Zero
-> type Frequency  = Quantity DFrequency
-
-> type DForce = Dim Pos1 Pos1 Neg2 Zero Zero Zero Zero
-> type Force  = Quantity DForce
-
-> type DPressure = Dim Neg1 Pos1 Neg2 Zero Zero Zero Zero
-> type DStress   = DPressure
-> type Pressure  = Quantity DPressure
-> type Stress    = Quantity DStress
-
-> type DEnergy         = Dim Pos2 Pos1 Neg2 Zero Zero Zero Zero
-> type DWork           = DEnergy
-> type DQuantityOfHeat = DEnergy
-> type Energy          = Quantity DEnergy
-> type Work            = Quantity DWork
-> type QuantityOfHeat  = Quantity DQuantityOfHeat
-
-> type DPower       = Dim Pos2 Pos1 Neg3 Zero Zero Zero Zero
-> type DRadiantFlux = DPower
-> type Power        = Quantity DPower
-> type RadiantFlux  = Quantity DRadiantFlux
-
-> type DElectricCharge        = Dim Zero Zero Pos1 Pos1 Zero Zero Zero
-> type DQuantityOfElectricity = DElectricCharge
-> type ElectricCharge         = Quantity DElectricCharge
-> type QuantityOfElectricity  = Quantity DQuantityOfElectricity
-
-> type DElectricPotential   = Dim Pos2 Pos1 Neg3 Neg1 Zero Zero Zero
-> type DPotentialDifference = DElectricPotential
-> type DElectromotiveForce  = DElectricPotential
-> type ElectricPotential    = Quantity DElectricPotential
-> type PotentialDifference  = Quantity DPotentialDifference
-> type ElectromotiveForce   = Quantity DElectromotiveForce
-
-> type DCapacitance = Dim Neg2 Neg1 Pos4 Pos2 Zero Zero Zero
-> type Capacitance  = Quantity DCapacitance
-
-> type DElectricResistance = Dim Pos2 Pos1 Neg3 Neg2 Zero Zero Zero
-> type ElectricResistance  = Quantity DElectricResistance
-
-> type DElectricConductance = Dim Neg2 Neg1 Pos3 Pos2 Zero Zero Zero
-> type ElectricConductance  = Quantity DElectricConductance
-
-> type DMagneticFlux = Dim Pos2 Pos1 Neg2 Neg1 Zero Zero Zero
-> type MagneticFlux  = Quantity DMagneticFlux
-
-> type DMagneticFluxDensity = Dim Zero Pos1 Neg2 Neg1 Zero Zero Zero
-> type MagneticFluxDensity  = Quantity DMagneticFluxDensity
-
-> type DInductance = Dim Pos2 Pos1 Neg2 Neg2 Zero Zero Zero
-> type Inductance  = Quantity DInductance
-
-> type DLuminousFlux = DLuminousIntensity
-> type LuminousFlux  = Quantity DLuminousFlux
-
-> type DIlluminance = Dim Neg2 Zero Zero Zero Zero Zero Pos1
-> type Illuminance  = Quantity DIlluminance
-
-> type DCelsiusTemperature = DThermodynamicTemperature
-> type CelsiusTemperature  = Quantity DCelsiusTemperature
-
-
-== Table 3b ==
-
-"SI derived units with special names and symbols admitted for reasons
-of safeguarding human health"
-
-> type DActivity = DFrequency -- Activity of a radionuclide.
-> type Activity  = Quantity DActivity
-
-> type DAbsorbedDose   = Dim Pos2 Zero Neg2 Zero Zero Zero Zero
-> type DSpecificEnergy = DAbsorbedDose
-> type DKerma          = DAbsorbedDose
-> type AbsorbedDose    = Quantity DAbsorbedDose
-> type SpecificEnergy  = Quantity DSpecificEnergy -- Specific energy imparted.
-> type Kerma           = Quantity DKerma
-
-> type DDoseEquivalent            = DAbsorbedDose
-> type DAmbientDoseEquivalent     = DDoseEquivalent
-> type DDirectionalDoseEquivalent = DDoseEquivalent
-> type DPersonalDoseEquivalent    = DDoseEquivalent
-> type DEquivalentDose            = DDoseEquivalent
-> type DoseEquivalent             = Quantity DDoseEquivalent
-> type AmbientDoseEquivalent      = DoseEquivalent
-> type DirectionalDoseEquivalent  = DoseEquivalent
-> type PersonalDoseEquivalent     = DoseEquivalent
-> type EquivalentDose             = DoseEquivalent
-
-
-== Table 4 ==
-
-"Examples of SI derived units expressed with the aid of SI derived
-units having special names and symbols."
-
-We use the same grouping as for table 2.
-
-> type DAngularVelocity = DFrequency
-> type AngularVelocity  = Quantity DAngularVelocity
-
-> type DAngularAcceleration = Dim Zero Zero Neg2 Zero Zero Zero Zero
-> type AngularAcceleration  = Quantity DAngularAcceleration
-
-> type DDynamicViscosity = Dim Neg1 Pos1 Neg1 Zero Zero Zero Zero
-> type DynamicViscosity  = Quantity DDynamicViscosity
-
-> type DMomentOfForce = DEnergy
-> type MomentOfForce  = Quantity DMomentOfForce
-
-> type DSurfaceTension = Dim Zero Pos1 Neg2 Zero Zero Zero Zero
-> type SurfaceTension  = Quantity DSurfaceTension
-
-> type DHeatFluxDensity = Dim Zero Pos1 Neg3 Zero Zero Zero Zero
-> type DIrradiance      = DHeatFluxDensity
-> type HeatFluxDensity  = Quantity DHeatFluxDensity
-> type Irradiance       = Quantity DIrradiance
-
-> type DRadiantIntensity = DPower
-> type RadiantIntensity  = Quantity DRadiantIntensity
-
-> type DRadiance = DIrradiance
-> type Radiance  = Quantity DRadiance
-
-> type DHeatCapacity = Dim Pos2 Pos1 Neg2 Zero Neg1 Zero Zero
-> type DEntropy      = DHeatCapacity
-> type HeatCapacity  = Quantity DHeatCapacity
-> type Entropy       = Quantity DEntropy
-
-> type DSpecificHeatCapacity = Dim Pos2 Zero Neg2 Zero Neg1 Zero Zero
-> type DSpecificEntropy      = DSpecificHeatCapacity
-> type SpecificHeatCapacity  = Quantity DSpecificHeatCapacity
-> type SpecificEntropy       = Quantity DSpecificEntropy
-
-Specific energy was already defined in table 3b.
-
-> type DThermalConductivity = Dim Pos1 Pos1 Neg3 Zero Neg1 Zero Zero
-> type ThermalConductivity  = Quantity DThermalConductivity
-
-> type DEnergyDensity = DPressure
-> type EnergyDensity  = Quantity DEnergyDensity
-
-> type DElectricFieldStrength = Dim Pos1 Pos1 Neg3 Neg1 Zero Zero Zero
-> type ElectricFieldStrength  = Quantity DElectricFieldStrength
-
-> type DElectricChargeDensity = Dim Neg3 Zero Pos1 Pos1 Zero Zero Zero
-> type ElectricChargeDensity  = Quantity DElectricChargeDensity
-
-> type DElectricFluxDensity = Dim Neg2 Zero Pos1 Pos1 Zero Zero Zero
-> type ElectricFluxDensity  = Quantity DElectricFluxDensity
-
-> type DPermittivity = Dim Neg3 Neg1 Pos4 Pos2 Zero Zero Zero
-> type Permittivity  = Quantity DPermittivity
-
-> type DPermeability = Dim Pos1 Pos1 Neg2 Neg2 Zero Zero Zero
-> type Permeability  = Quantity DPermeability
-
-> type DMolarEnergy = Dim Pos2 Pos1 Neg2 Zero Zero Neg1 Zero
-> type MolarEnergy  = Quantity DMolarEnergy
-
-> type DMolarEntropy      = Dim Pos2 Pos1 Neg2 Zero Neg1 Neg1 Zero
-> type DMolarHeatCapacity = DMolarEntropy
-> type MolarEntropy       = Quantity DMolarEntropy
-> type MolarHeatCapacity  = Quantity DMolarHeatCapacity
-
-> type DExposure = Dim Zero Neg1 Pos1 Pos1 Zero Zero Zero
-> type Exposure  = Quantity DExposure -- Exposure to x and gamma rays.
-
-> type DAbsorbedDoseRate = Dim Pos2 Zero Neg3 Zero Zero Zero Zero
-> type AbsorbedDoseRate  = Quantity DAbsorbedDoseRate
-
-
-= Quantities not defined in [1] =
-
-Here we define additional quantities on an as-needed basis. We also
-provide some synonyms that we anticipate will be useful.
-
-> type DImpulse = Dim Pos1 Pos1 Neg1 Zero Zero Zero Zero
-> type Impulse  = Quantity DImpulse
-
-> type DMassFlow = Dim Zero Pos1 Neg1 Zero Zero Zero Zero
-> type MassFlow  = Quantity DMassFlow
-
-> type DGravitationalParameter = Dim Pos3 Zero Neg2 Zero Zero Zero Zero
-> type GravitationalParameter  = Quantity DGravitationalParameter
-
-> type DKinematicViscosity = Dim Pos2 Zero Neg1 Zero Zero Zero Zero
-> type KinematicViscosity  = Quantity DKinematicViscosity
-
-> type DFirstMassMoment = Dim Pos1 Pos1 Zero Zero Zero Zero Zero
-> type FirstMassMoment = Quantity DFirstMassMoment
-
-> type DMomentOfInertia = Dim Pos2 Pos1 Zero Zero Zero Zero Zero
-> type MomentOfInertia = Quantity DMomentOfInertia
-
-> type DAngularMomentum = Dim Pos2 Pos1 Neg1 Zero Zero Zero Zero
-> type AngularMomentum = Quantity DAngularMomentum
-
-> type Angle = PlaneAngle -- Abbreviation
-> type DAngle = DPlaneAngle -- Abbreviation
-
-> type Thrust = Force
-> type DThrust = DForce
-
-> type Torque = MomentOfForce
-> type DTorque = DMomentOfForce
-
-> type EnergyPerUnitMass = SpecificEnergy
-> type DEnergyPerUnitMass = DSpecificEnergy
-
-
-= References =
-
-[1] http://physics.nist.gov/Pubs/SP811/
diff --git a/Numeric/Units/Dimensional/QuantitiesTest.hs b/Numeric/Units/Dimensional/QuantitiesTest.hs
deleted file mode 100644
--- a/Numeric/Units/Dimensional/QuantitiesTest.hs
+++ /dev/null
@@ -1,88 +0,0 @@
-module Numeric.Units.Dimensional.QuantitiesTest where
-
-import Numeric.Units.Dimensional.Prelude
-import qualified Prelude
-
--- These definitions simply verify that the type synonyms are
--- consistent with the appropriate units from table 2. If the
--- definitions compile the type synonyms are good.
-
-x1 :: Area Double
-x1 = 1 *~ meter ^ pos2
-x2 :: Volume Double
-x2 = 1 *~ meter ^ pos3
-x3 :: Velocity Double
-x3 = 1 *~ (meter / second)
-x4 :: Acceleration Double
-x4 = 1 *~ (meter / second ^ pos2)
-x5 :: WaveNumber Double
-x5 = 1 *~ meter ^ neg1
-x6 :: Density Double
-x6 = 1 *~ (kilo gram / meter ^ pos3)
-x7 :: SpecificVolume Double
-x7 = 1 *~ (meter ^ pos3 / kilo gram)
-x8 :: CurrentDensity Double
-x8 = 1 *~ (ampere / meter ^ pos2)
-x9 :: MagneticFieldStrength Double
-x9 = 1 *~ (ampere / meter)
-x10 :: Concentration Double
-x10 = 1 *~ (mole / meter ^ pos3)
-x11 :: Luminance Double
-x11 = 1 *~ (candela / meter ^ pos2)
-
--- Tables 3a and 3b are implicitely tested by the corresponding
--- unit definitions.
-
--- Verification of table 4. If the definitions compile the type
--- synonyms are good.
-
-y1 :: AngularVelocity Double
-y1 = 1 *~ (radian / second)
-y2 :: AngularAcceleration Double
-y2 = 1 *~ (radian / second ^ pos2)
-y3 :: DynamicViscosity Double
-y3 = 1 *~ (pascal * second)
-y4 :: MomentOfForce Double
-y4 = 1 *~ (newton * meter)
-y5 :: SurfaceTension Double
-y5 = 1 *~ (newton / meter)
-y6 :: HeatFluxDensity Double
-y6 = 1 *~ (watt / meter ^ pos2)
-y7 :: RadiantIntensity Double
-y7 = 1 *~ (watt / steradian)
-y8 :: Radiance Double
-y8 = 1 *~ (watt / (meter ^ pos2 * steradian))
-y9 :: HeatCapacity Double
-y9 = 1 *~ (joule / kelvin)
-y10 :: SpecificHeatCapacity Double
-y10 = 1 *~ (joule / (kilo gram * kelvin))
-y11 :: ThermalConductivity Double
-y11 = 1 *~ (watt / (meter * kelvin))
-y12 :: EnergyDensity Double
-y12 = 1 *~ (joule / meter ^ pos3)
-y13 :: ElectricFieldStrength Double
-y13 = 1 *~ (volt / meter)
-y14 :: ElectricChargeDensity Double
-y14 = 1 *~ (coulomb / meter ^ pos3)
-y15 :: ElectricFluxDensity Double
-y15 = 1 *~ (coulomb / meter ^ pos2)
-y16 :: Permittivity Double
-y16 = 1 *~ (farad / meter)
-y17 :: Permeability Double
-y17 = 1 *~ (henry / meter)
-y18 :: MolarEnergy Double
-y18 = 1 *~ (joule / mole)
-y19 :: MolarEntropy Double
-y19 = 1 *~ (joule / (mole * kelvin))
-y20 :: Exposure Double
-y20 = 1 *~ (coulomb / kilo gram)
-y21 :: AbsorbedDoseRate Double
-y21 = 1 *~ (gray / second)
-
--- Other quantitites.
-mu :: GravitationalParameter Double
-mu = 398600.4418 *~ (kilo meter ^ pos3 / second ^ pos2)
-
--- Dummy main function.
-main = Prelude.putStrLn "If I compiled I'm OK!"
-
diff --git a/Numeric/Units/Dimensional/SIUnits.lhs b/Numeric/Units/Dimensional/SIUnits.lhs
deleted file mode 100644
--- a/Numeric/Units/Dimensional/SIUnits.lhs
+++ /dev/null
@@ -1,278 +0,0 @@
-Numeric.Dimensional.SIUnits
-Bjorn Buckwalter, bjorn.buckwalter@gmail.com
-License: BSD3
-
-
-= Summary =
-
-This module defines the SI prefixes, the SI base units and the SI
-derived units. It also defines the units outside of the SI that are
-accepted for use with the SI. Any chapters, sections or tables
-referenced are from [1] unless otherwise specified.
-
-> {- |
->    Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
->    License    : BSD3
->
->    Maintainer : bjorn.buckwalter@gmail.com
->    Stability  : Stable
->    Portability: GHC only?
->
-> Please refer to the literate Haskell code for documentation of both API
-> and implementation.
-> -}
-
-> module Numeric.Units.Dimensional.SIUnits where
-
-> import Numeric.Units.Dimensional
-> import Numeric.Units.Dimensional.Quantities
-> import Numeric.NumType ( neg1, neg2, pos2, pos3 )
-> import Data.Time.Clock (DiffTime)
-> import Prelude ( (.), Num, Real (toRational), Fractional (fromRational), Floating, recip )
-> import qualified Prelude
-
-
-= SI prefixes (section 4.4) =
-
-Prefixes are used to form decimal multiples and submultiples of SI
-Units as described in section 4.4. We will define the SI prefixes
-in terms of the 'prefix' function which applies a scale factor to a
-unit.
-
-We define all SI prefixes from Table 5. Multiples first.
-
-> deka, deca, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta
->   :: Num a => Unit d a -> Unit d a
-> deka  = prefix 10 -- International English.
-> deca  = deka      -- American English.
-> hecto = prefix 100
-> kilo  = prefix 1000
-> mega  = kilo . kilo
-> giga  = kilo . mega
-> tera  = kilo . giga
-> peta  = kilo . tera
-> exa   = kilo . peta
-> zetta = kilo . exa
-> yotta = kilo . zetta
-
-Then the submultiples.
-
-> deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto
->   :: Fractional a => Unit d a -> Unit d a
-> deci  = prefix 0.1
-> centi = prefix 0.01
-> milli = prefix 1e-3
-> micro = prefix 1e-6
-> nano  = prefix 1e-9
-> pico  = prefix 1e-12
-> femto = prefix 1e-15
-> atto  = prefix 1e-18
-> zepto = prefix 1e-21
-> yocto = prefix 1e-24
-
-By defining SI prefixes as functions applied to a 'Unit' we satisfy
-section 6.2.6 "Unacceptability of stand-alone prefixes".
-
-
-= SI base units (section 4.1) =
-
-Now we will define the SI base unitsi from section 4.1. To avoid a
-myriad of one-letter functions that would doubtlessly cause clashes
-and frustration in users' code we spell out all unit names in full,
-as we did for prefixes. We also elect to spell the unit names in
-singular form, as allowed by section 9.7 "Other spelling conventions".
-
-We define the SI base units in the order of table 1.
-
-> metre, meter :: Num a => Unit DLength a
-> metre = Dimensional 1 -- International English.
-> meter = metre         -- American English.
-
-For mass the SI base unit is kilogram. For sensible prefixes we
-define gram here (see section 6.2.7 "Prefixes and the kilogram").
-The drawback is that we are forced to use 'Fractional'.
-
-> gram    :: Fractional a => Unit DMass a
-> gram    = Dimensional 1e-3
-> second  :: Num a => Unit DTime a
-> second  = Dimensional 1
-> ampere  :: Num a => Unit DElectricCurrent a
-> ampere  = Dimensional 1
-> kelvin  :: Num a => Unit DThermodynamicTemperature a
-> kelvin  = Dimensional 1
-> mole    :: Num a => Unit DAmountOfSubstance a
-> mole    = Dimensional 1
-> candela :: Num a => Unit DLuminousIntensity a
-> candela = Dimensional 1
-
-
-= DiffTime conversion =
-
-It is not within the scope of this library to handle the complex
-task of date and time arithmetic. It is recommended to use the
-'Data.Time' library for handling dates and using 'Time' quantities
-only when time differences are involved in calculations with other
-quantities. In order to convert between the 'DiffTime' data type
-in the 'Data.Time' library and 'Time' quantities we provide the
-functions 'fromDiffTime' and 'toDiffTime'.
-
-> fromDiffTime :: (Fractional a) => DiffTime -> Time a
-> fromDiffTime = (*~ second) . fromRational . toRational
-> toDiffTime :: (Real a, Fractional a) => Time a -> DiffTime
-> toDiffTime = fromRational . toRational . (/~ second)
-
-
-= SI derived units (section 4.2) =
-
-Before defining the derived units themselves we provide type synonyms
-for derived quantities and their dimensionalities. For lack of better
-organization we provide definitions grouped by table in [1].
-
-
-== Table 3a ==
-
-"SI derived units with special names and symbols, including the
-radian and steradian."
-
-> radian :: Fractional a => Unit DPlaneAngle a
-> radian = one -- meter * meter ^ neg1
-> steradian :: Fractional a => Unit DSolidAngle a
-> steradian = one -- meter ^ pos2 * meter ^ neg2
-> hertz :: Fractional a => Unit DFrequency a
-> hertz = second ^ neg1
-> newton :: Fractional a => Unit DForce a
-> newton = kilo gram * meter * second ^ neg2
-> pascal :: Fractional a => Unit DPressure a
-> pascal = newton / meter ^ pos2
-> joule :: Fractional a => Unit DEnergy a
-> joule = newton * meter
-> watt :: Fractional a => Unit DPower a
-> watt = joule / second
-> coulomb :: Fractional a => Unit DElectricCharge a
-> coulomb = second * ampere
-> volt :: Fractional a => Unit DElectricPotential a
-> volt = watt / ampere
-> farad :: Fractional a => Unit DCapacitance a
-> farad = coulomb / volt
-> ohm :: Fractional a => Unit DElectricResistance a
-> ohm = volt / ampere
-> siemens :: Fractional a => Unit DElectricConductance a
-> siemens = ampere / volt
-> weber :: Fractional a => Unit DMagneticFlux a
-> weber = volt * second
-> tesla :: Fractional a => Unit DMagneticFluxDensity a
-> tesla = weber / meter ^ pos2
-> henry :: Fractional a => Unit DInductance a
-> henry = weber / ampere
-
-We defer the definition of Celcius temperature to the end (would
-appear here if we stricly followed table 3a).
-
-> lumen :: Fractional a => Unit DLuminousFlux a
-> lumen = candela * steradian
-> lux :: Fractional a => Unit DIlluminance a
-> lux = lumen / meter ^ pos2
-
-=== Degree Celsius ===
-
-A problematic area is units which increase proportionally to the
-base SI units but cross zero at a different point. An example would
-be degrees Celsius (see section 4.2.1.1). The author feels that it
-is appropriate to define a unit for use with relative quantities
-(taking only into account the proportionality) and complement the
-unit with functions for converting absolute values.
-
-> degreeCelsius :: Num a => Unit DCelsiusTemperature a
-> degreeCelsius = kelvin
-
-The function 'fromDegreeCelsiusAbsolute' should be used in lieu of
-"*~ degreeCelsius" when working with absolute temperatures. Similarily,
-'toDegreeCelsiusAbsolute' should be used in lieu of "/~ degreeCelsius"
-when working with absolute temperatures.
-
-> fromDegreeCelsiusAbsolute :: Fractional a => a -> ThermodynamicTemperature a
-> fromDegreeCelsiusAbsolute x = x *~ degreeCelsius + 273.15 *~ degreeCelsius
-> toDegreeCelsiusAbsolute :: Fractional a => ThermodynamicTemperature a -> a
-> toDegreeCelsiusAbsolute x = (x - 273.15 *~ degreeCelsius) /~ degreeCelsius
-
-
-== Table 3b ==
-
-"SI derived units with special names and symbols admitted for reasons
-of safeguarding human health"
-
-We use the same grouping as for table 3a.
-
-> becquerel :: Fractional a => Unit DActivity a
-> becquerel = second ^ neg1
-
-Above we gave a new name to the dimensionality instead of reusing
-'Frequency' in the quantity type definition. This will allow GHCi
-be more specific when queried for the type of 'becquerel'. For
-quantity types without a specific unit we don't bother doing this
-(though perhaps we should in case there is a non-SI unit for the
-quantity type?).
-
-> gray :: Fractional a => Unit DAbsorbedDose a
-> gray = joule / kilo gram
-> sievert :: Fractional a => Unit DDoseEquivalent a
-> sievert = joule / kilo gram
-
-
-= Units outside the SI =
-
-There are several units that are not strictly part of the SI but
-are either permanently or temporarily accepted for use with the SI.
-We define the permanently accepted ones in this module.
-
-== Table 6 ==
-
-"Units accepted for use with the SI."
-
-We start with time which we grant exclusive rights to 'minute' and
-'second'.
-
-> minute, hour, day :: Num a => Unit DTime a
-> minute = prefix 60 second
-> hour   = prefix 60 minute
-> day    = prefix 24 hour -- Mean solar day.
-
-Since 'minute' and 'second' are already in use for time we use
-'arcminute' and 'arcsecond' [2] for plane angle instead.
-
-> degree, arcminute, arcsecond :: Floating a => Unit DPlaneAngle a
-> degree = prefix (Prelude.pi Prelude./ 180) radian
-> arcminute = prefix (recip 60) degreeOfArc
-> arcsecond = prefix (recip 60) minuteOfArc
-
-Alternate (longer) forms of the above. In particular 'degreeOfArc'
-can be used if there is a percieved need to disambiguate from e.g.
-temperature.
-
-> degreeOfArc, minuteOfArc, secondOfArc :: Floating a => Unit DPlaneAngle a
-> degreeOfArc = degree
-> secondOfArc = arcsecond
-> minuteOfArc = arcminute
-
-> litre, liter :: Fractional a => Unit DVolume a
-> litre = deci meter ^ pos3 -- International English.
-> liter = litre             -- American English.
-
-> tonne, metricTon :: Fractional a => Unit DMass a
-> tonne     = prefix 1000 (kilo gram) -- Name in original SI text.
-> metricTon = tonne                   -- American name.
-
-In 2012 the IAU redefined the astronomical unit as a conventional
-unit of length directly tied to the meter, with a length of exactly
-149,597,870,700 m and the official abbreviation of au[3].
-
-> astronomicalUnit :: Num a => Unit DLength a
-> astronomicalUnit = prefix 149597870700 meter
-
-
-= References =
-
-[1] http://physics.nist.gov/Pubs/SP811/
-[2] http://en.wikipedia.org/wiki/Minute_of_arc
-[3] http://en.wikipedia.org/wiki/Astronomical_unit
-
diff --git a/Numeric/Units/Dimensional/Test.hs b/Numeric/Units/Dimensional/Test.hs
deleted file mode 100644
--- a/Numeric/Units/Dimensional/Test.hs
+++ /dev/null
@@ -1,35 +0,0 @@
-{-# LANGUAGE NoMonomorphismRestriction #-}
-
-module Numeric.Units.Dimensional.Test where
-
-import Numeric.Units.Dimensional.Prelude
-import qualified Prelude
-import Test.HUnit
-
-testPower = TestLabel "Power test" $ TestList
-    [ TestCase $ (9 *~ one) @=? (3 *~ one) ^ pos2
-    , TestCase $ (1 *~ one) @=? (12.1231 *~ one) ^ zero
-    , TestCase $ (0.25 *~ one) @=? (2 *~ one) ^ neg2
-    ]
-
-testDimensionless = TestLabel "Dimensionless test" $ TestList
-    [ TestCase $ (3 Prelude.** 2) *~ one @=? (3 *~ one) ** (2 *~ one)
-    ]
-
-testShow = TestLabel "Test 'Show' instance" $ TestList
-    [ TestCase $ show (1 *~ one) @?= "1"
-    , TestCase $ show (2 *~ meter) @?= "2 m"
-    , TestCase $ show (2.0 *~ (meter / second)) @?= "2.0 m s^-1"
-    , TestCase $ show (2.0 *~ (meter ^ pos2 / second ^ pos2)) @?= "2.0 m^2 s^-2"
-    , TestCase $ show (undefined :: DVelocity) @?= "m s^-1"
-    ]
-
--- Collect the test cases.
-tests = TestList
-    [ testPower
-    , testDimensionless
-    , testShow
-    ]
-
-main = runTestTT tests
-
diff --git a/README b/README
deleted file mode 100644
--- a/README
+++ /dev/null
@@ -1,10 +0,0 @@
-For documentation see the literate haskell source code.
-
-For project information (issues, updates, wiki, examples) see:
-    http://code.google.com/p/dimensional/
-
-To install (requires GHC 6.6 or later):
-    runhaskell Setup.lhs configure
-    runhaskell Setup.lhs build
-    runhaskell Setup.lhs install
-
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,53 @@
+dimensional
+==============
+
+This library provides statically-checked dimensional arithmetic for physical quantities, using the 7 SI base dimensions.
+
+Data kinds and closed type families provide a flexible, safe, and discoverable implementation that leads to largely self-documenting
+client code.
+
+[![Build Status](https://travis-ci.org/bjornbm/dimensional-dk.svg?branch=master)](https://travis-ci.org/bjornbm/dimensional-dk)
+[![Hackage Version](http://img.shields.io/hackage/v/dimensional.svg)](http://hackage.haskell.org/package/dimensional)
+
+Usage
+-----
+
+Simply importing `Numeric.Units.Dimensional.Prelude` provides access to dimensional arithmetic opertors, SI units and other common units
+accepted for use with the SI, and convenient aliases for quantities with commonly used dimensions.
+
+The `Unit d a` type represents a unit with dimension `d`, whose conversion factor to the coherent SI base unit of the corresponding dimension
+is represented by a value of type `a`. `a` is commonly chosen to be `Double`, but can be any `Floating` type. Where possible, support is also
+provided for `Fractional` or `Num` values.
+
+Similarly, the `Quantity d a` type represents a quantity with dimension `d`, whose numeric value is of type `a`. Aliases allow the use of, e.g.,
+`Length Double` to mean `Quantity DLength Double`. A complete list of available aliases is given in the haddock documentation for the
+`Numeric.Units.Dimensional.Quantities`.
+
+```haskell
+{-# LANGUAGE NoImplicitPrelude #-}
+
+import Numeric.Units.Dimensional.Prelude
+import Numeric.Units.Dimensional.NonSI (gee)
+
+radiusOfEarth :: Length Double
+radiusOfEarth = 6371 *~ kilo meter
+
+massOfEarth :: Mass Double
+massOfEarth = 5.97e24 *~ kilo gram
+
+g :: GravitationalParameter Double
+g = 6.67384e-11 *~ (meter^pos3 * (kilo gram)^neg1 * second^neg2)
+
+gravitationalFieldStrength :: Mass a -> Length a -> Acceleration a
+gravitationalFieldStrength m r = g * m / r^pos2
+
+approximateAccelerationDueToGravityOnEarth = gravitationalFieldStrength massOfEarth radiusOfEarth
+
+differenceFromStandardValue = approximateAccelerationDueToGravityOnEarth /~ gee
+```
+
+Contributing
+------------
+
+For project information (issues, updates, wiki, examples) see:
+  https://github.com/bjornbm/dimensional-dk
diff --git a/Setup.lhs b/Setup.lhs
--- a/Setup.lhs
+++ b/Setup.lhs
@@ -1,3 +1,3 @@
-#!/usr/bin/env runhaskell
-> import Distribution.Simple
+#!/usr/bin/env runhaskell
+> import Distribution.Simple
 > main = defaultMain
diff --git a/Test.hs b/Test.hs
deleted file mode 100644
--- a/Test.hs
+++ /dev/null
@@ -1,8 +0,0 @@
-import qualified Numeric.Units.Dimensional.Test
-import qualified Numeric.Units.Dimensional.QuantitiesTest
-import qualified Numeric.Units.Dimensional.ExtensibleTest
-
-main = do
-  Numeric.Units.Dimensional.Test.main
-  Numeric.Units.Dimensional.QuantitiesTest.main
-  Numeric.Units.Dimensional.ExtensibleTest.main
diff --git a/benchmarks/Main.hs b/benchmarks/Main.hs
new file mode 100644
--- /dev/null
+++ b/benchmarks/Main.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Main where
+
+import Criterion.Main
+import Numeric.Units.Dimensional.Prelude
+import qualified Prelude as P
+
+main :: IO ()
+main = defaultMain [
+         bench "RawArithmetic" $ nf rawArithmetic 1000
+       , bench "Arithmetic" $ nf arithmetic 1000
+       ]
+
+rawArithmetic :: Int -> [Double]
+rawArithmetic n = fmap (P./ 3.7) $ [1.0 .. fromIntegral n]
+
+arithmetic :: Int -> [Density Double]
+arithmetic n = fmap (/ (3.7 *~ cubic meter)) $ [1.0 .. fromIntegral n] *~~ kilo gram
diff --git a/changelog.md b/changelog.md
deleted file mode 100644
--- a/changelog.md
+++ /dev/null
@@ -1,74 +0,0 @@
-0.13.0.2 (2015-04)
-------------------
-*  Corrected definition of lumen.
-
-
-0.13.0.1 (2014-09)
-------------------
-*  Bumped time dependency to < 1.6.
-
-
-0.13 (2014-02)
---------------
-*  Bump major version (should have been done in previous version).
-
-
-0.12.3 (2014-02)
-----------------
-*  Bump numtype dependency to 1.1 (GHC 7.8.1 compatibility fix).
-*  Added `Torque`.
-*  Added D.. for the type synonym quantities (e.g., `Angle`).
-
-
-0.12.2 (2013-11)
-----------------
-*  Added `FirstMassMoment`, `MomentOfInertia`, `AngularMomentum`.
-*  Improved unit numerics.
-
-
-0.12.1 (2013-07)
-----------------
-*  Typeable Dimensionals.
-
-
-0.12 (2013-06)
---------------
-*  Polymorphic `_0` (closes issue 39).
-*  Added `astronomicalUnit`.
-*  Added imperial volume units.
-*  Added 'mil' (=inch/1000).
-*  Added [`tau`][3].
-*  Added `KinematicViscosity`.
-
-[3]: http://tauday.com/tau-manifesto
-
-
-0.10.1.2 (2011-09)
-------------------
-*  Bumped time dependency to < 1.5.
-
-
-0.10.1.2 (2011-08)
-------------------
-*  Bumped time dependency to < 1.4.
-
-
-0.10.1 (2011-08)
-------------------
-GHC 7.2.1 compatibility fix:
-
-*  Increased CGS context-stack to 30.
-
-
-0.10 (2011-05)
--------------
-See the [announcement][2].
-
-[2]: http://flygdynamikern.blogspot.se/2011/05/announce-dimensional-010.html
-
-
-0.9 (2011-04)
--------------
-See the [announcement][1].
-
-[1]: http://flygdynamikern.blogspot.se/2011/04/announce-dimensional-09.html
diff --git a/dimensional.cabal b/dimensional.cabal
--- a/dimensional.cabal
+++ b/dimensional.cabal
@@ -1,36 +1,88 @@
-Name:                dimensional
-Version:             0.13.0.2
-License:             BSD3
-License-File:        LICENSE
-Copyright:           Bjorn Buckwalter 2006-2015
-Author:              Bjorn Buckwalter
-Maintainer:          bjorn@buckwalter.se
-Stability:           mostly stable
-Homepage:            http://dimensional.googlecode.com/
-Synopsis:            Statically checked physical dimensions.
-Description:
-    Dimensional is a library providing data types for performing arithmetic
-    with physical quantities and units. Information about the physical
-    dimensions of the quantities and units is embedded in their types and the
-    validity of operations is verified by the type checker at compile time.
-    The boxing and unboxing of numerical values as quantities is done by
-    multiplication and division with units. The library is designed to, as
-    far as is practical, enforce/encourage best practices of unit usage.
-Category:            Math, Physics
-Build-Type:          Simple
-Build-Depends:       base < 5, time < 1.6, numtype < 1.2
-Exposed-Modules:     Numeric.Units.Dimensional,
-                     Numeric.Units.Dimensional.Prelude,
-                     Numeric.Units.Dimensional.Quantities,
-                     Numeric.Units.Dimensional.SIUnits,
-                     Numeric.Units.Dimensional.NonSI,
-                     Numeric.Units.Dimensional.Extensible,
-                     Numeric.Units.Dimensional.CGS
-Extra-source-files:  README,
-                     changelog.md,
-                     Test.hs
-                     Numeric/Units/Dimensional/Test.hs,
-                     Numeric/Units/Dimensional/QuantitiesTest.hs,
-                     Numeric/Units/Dimensional/ExtensibleTest.lhs,
-                     examples/README,
-                     examples/GM.lhs
+name:                dimensional
+version:             1.0.0.0
+license:             BSD3
+license-file:        LICENSE
+copyright:           Bjorn Buckwalter 2006-2015
+author:              Bjorn Buckwalter
+maintainer:          bjorn@buckwalter.se
+stability:           experimental
+homepage:            https://github.com/bjornbm/dimensional-dk/
+category:            Math, Physics
+synopsis:            Statically checked physical dimensions,
+                     using Type Families and Data Kinds.
+cabal-version:       >= 1.10
+tested-with:         GHC == 7.8.4, GHC == 7.10.1, GHC == 7.10.2
+build-type:          Simple
+
+description:
+
+    Dimensional is a library providing data types for performing arithmetic
+    with physical quantities and units. Information about the physical
+    dimensions of the quantities and units is embedded in their types and the
+    validity of operations is verified by the type checker at compile time.
+    The boxing and unboxing of numerical values as quantities is done by
+    multiplication and division with units. The library is designed to, as
+    far as is practical, enforce/encourage best practices of unit usage.
+
+    Version 1 of the dimensional package differs from earlier version in that
+    the dimension tracking is implemented using Closed Type Families and Data Kinds
+    rather than functional dependencies. This enables a number of features, including
+    improved support for unit names and quantities with statically-unknown dimensions.
+
+    Requires GHC 7.8 or later.
+
+extra-source-files:  README.md,
+                     examples/README,
+                     examples/GM.lhs
+
+source-repository head
+  type:     git
+  location: https://github.com/bjornbm/dimensional-dk/
+
+library
+  build-depends:       base >= 4.7 && < 5,
+                       deepseq >= 1.3,
+                       exact-pi >= 0.2.1.1 && < 0.3,
+                       numtype-dk >= 0.5 && < 1.1,
+                       vector >= 0.10
+  hs-source-dirs:      src
+  default-language:    Haskell2010
+  ghc-options:         -Wall
+  exposed-modules:     Numeric.Units.Dimensional,
+                       Numeric.Units.Dimensional.Prelude,
+                       Numeric.Units.Dimensional.Quantities,
+                       Numeric.Units.Dimensional.SIUnits,
+                       Numeric.Units.Dimensional.NonSI,
+                       Numeric.Units.Dimensional.Dimensions,
+                       Numeric.Units.Dimensional.Dimensions.TermLevel,
+                       Numeric.Units.Dimensional.Dimensions.TypeLevel,
+                       Numeric.Units.Dimensional.Dynamic,
+                       Numeric.Units.Dimensional.Functor,
+                       Numeric.Units.Dimensional.UnitNames,
+                       Numeric.Units.Dimensional.UnitNames.InterchangeNames,
+                       Numeric.Units.Dimensional.Variants
+  other-modules:       Numeric.Units.Dimensional.UnitNames.Internal
+
+test-suite tests
+  type:                exitcode-stdio-1.0
+  main-is:             Test.hs
+  hs-source-dirs:      tests
+  other-modules:       Numeric.Units.Dimensional.QuantitiesTest,
+                       Numeric.Units.Dimensional.Test
+  default-language:    Haskell2010
+  ghc-options:         -Wall
+  build-depends:       dimensional,
+                       HUnit,
+                       base
+
+benchmark simple
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      benchmarks
+  main-is:             Main.hs
+  build-depends:       base,
+                       criterion,
+                       deepseq,
+                       dimensional
+  default-language:    Haskell2010
+  ghc-options:         -O2
+  
diff --git a/examples/GM.lhs b/examples/GM.lhs
--- a/examples/GM.lhs
+++ b/examples/GM.lhs
@@ -1,93 +1,94 @@
-
-= GM calculation =
-
-Several representation can be used to describe a satellite's orbit. Two
-of the most popular are the cartesian state vector (position and
-velocity vectors) and the keplerian elements. Conversion between the two
-representations is fairly straight-forward but requires an assumption
-to be made about the universal gravitational constant 'G' and the mass
-'M' of the body the satellite is orbiting. In practice they are often
-combined into a parameter "mu = GM" where the magnitude of 'mu' is
-empirically better known that the magnitudes of 'G' and 'M' individually.
-
-*The problem:* Given two representations of the same satellite orbit -- one
-using the cartesian state vector and using keplerian elements, both at the
-same epoch -- determine the value of 'mu' used to convert between the two.
-{{{
-
-> module GM where
-
-> import Numeric.Units.Dimensional.Prelude
-> import qualified Prelude
-
-}}}
-The state vector describing the orbit at epoch.
-{{{
-
-> x     =   4383.9449203752        *~ kilo meter
-> y     = (-41940.917505092)       *~ kilo meter
-> z     =     22.790255916589      *~ kilo meter
-> x_dot =      3.0575666627812     *~ (kilo meter / second)
-> y_dot =      0.32047068607303    *~ (kilo meter / second)
-> z_dot =      0.00084729371755294 *~ (kilo meter / second)
-
-}}}
-From the state vector we calculate the distance from the reference frame center at epoch and the velocity squared at epoch.
-{{{
-
-> r = sqrt (x ^ pos2 + y ^ pos2 + z ^ pos2)
-> v = sqrt (x_dot ^ pos2 + y_dot ^ pos2 + z_dot ^ pos2)
-
-}}}
-The kinetic energy per unit mass at epoch is a function of the velocity.
-{{{
-
-> e_kin :: EnergyPerUnitMass Double
-> e_kin = v ^ pos2 / _2
-
-}}}
-The only keplerian element we need for this calculation is the semi-major axis.
-{{{
-
-> semi_major_axis = 42165.221455 *~ kilo meter
-
-}}}
-The expression for 'mu' is obtained by solving the following equation system:
-
-    e_pot = - mu / r,
-
-    e_tot = - mu / 2a,
-
-    e_tot = e_pot + e_kin,
-
-which gives:
-
-    mu = e_kin / (1 / r - 1 / 2a).
-
-{{{
-
-> mu = e_kin / (_1 / r - _1 / (_2 * semi_major_axis))
-
-}}}
-Wrap up with a main function showing the value of 'mu' in desired units.
-{{{
-
-> main = putStrLn $ "The value used for GM was " ++ show mu
-
-}}}
-Loading this module in 'ghci' and running 'main' produces the following output.
-{{{
-   ___         ___ _
-  / _ \ /\  /\/ __(_)
- / /_\// /_/ / /  | |      GHC Interactive, version 6.6.1, for Haskell 98.
-/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
-\____/\/ /_/\____/|_|      Type :? for help.
-
-Loading package base ... linking ... done.
-[1 of 1] Compiling GM               ( GM.lhs, interpreted )
-Ok, modules loaded: GM.
-*GM> main
-Loading package dimensional-0.5 ... linking ... done.
-The value used for GM was 3.986004400008003e14 m^3 s^-2
-*GM>
-}}}
+
+= GM calculation =
+
+Several representation can be used to describe a satellite's orbit. Two
+of the most popular are the cartesian state vector (position and
+velocity vectors) and the keplerian elements. Conversion between the two
+representations is fairly straight-forward but requires an assumption
+to be made about the universal gravitational constant 'G' and the mass
+'M' of the body the satellite is orbiting. In practice they are often
+combined into a parameter "mu = GM" where the magnitude of 'mu' is
+empirically better known that the magnitudes of 'G' and 'M' individually.
+
+*The problem:* Given two representations of the same satellite orbit -- one
+using the cartesian state vector and using keplerian elements, both at the
+same epoch -- determine the value of 'mu' used to convert between the two.
+{{{
+
+> {-# LANGUAGE NegativeLiterals #-}
+> module GM where
+
+> import Numeric.Units.Dimensional.Prelude
+> import qualified Prelude
+
+}}}
+The state vector describing the orbit at epoch.
+{{{
+
+> x     =   4383.9449203752        *~ kilo meter
+> y     = -41940.917505092       *~ kilo meter
+> z     =     22.790255916589      *~ kilo meter
+> x_dot =      3.0575666627812     *~ (kilo meter / second)
+> y_dot =      0.32047068607303    *~ (kilo meter / second)
+> z_dot =      0.00084729371755294 *~ (kilo meter / second)
+
+}}}
+From the state vector we calculate the distance from the reference frame center at epoch and the velocity squared at epoch.
+{{{
+
+> r = sqrt (x ^ pos2 + y ^ pos2 + z ^ pos2)
+> v = sqrt (x_dot ^ pos2 + y_dot ^ pos2 + z_dot ^ pos2)
+
+}}}
+The kinetic energy per unit mass at epoch is a function of the velocity.
+{{{
+
+> e_kin :: EnergyPerUnitMass Double
+> e_kin = v ^ pos2 / _2
+
+}}}
+The only keplerian element we need for this calculation is the semi-major axis.
+{{{
+
+> semi_major_axis = 42165.221455 *~ kilo meter
+
+}}}
+The expression for 'mu' is obtained by solving the following equation system:
+
+    e_pot = - mu / r,
+
+    e_tot = - mu / 2a,
+
+    e_tot = e_pot + e_kin,
+
+which gives:
+
+    mu = e_kin / (1 / r - 1 / 2a).
+
+{{{
+
+> mu = e_kin / (_1 / r - _1 / (_2 * semi_major_axis))
+
+}}}
+Wrap up with a main function showing the value of 'mu' in desired units.
+{{{
+
+> main = putStrLn $ "The value used for GM was " ++ show mu
+
+}}}
+Loading this module in 'ghci' and running 'main' produces the following output.
+{{{
+   ___         ___ _
+  / _ \ /\  /\/ __(_)
+ / /_\// /_/ / /  | |      GHC Interactive, version 6.6.1, for Haskell 98.
+/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
+\____/\/ /_/\____/|_|      Type :? for help.
+
+Loading package base ... linking ... done.
+[1 of 1] Compiling GM               ( GM.lhs, interpreted )
+Ok, modules loaded: GM.
+*GM> main
+Loading package dimensional-0.5 ... linking ... done.
+The value used for GM was 3.986004400008003e14 m^3 s^-2
+*GM>
+}}}
diff --git a/examples/README b/examples/README
--- a/examples/README
+++ b/examples/README
@@ -1,2 +1,2 @@
-See the project wiki at http://dimensional.googlecode.com for more examples.
-
+See the project wiki at http://dimensional.googlecode.com for more examples.
+
diff --git a/src/Numeric/Units/Dimensional.hs b/src/Numeric/Units/Dimensional.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional.hs
@@ -0,0 +1,901 @@
+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-# LANGUAGE AutoDeriveTypeable #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE MultiParamTypeClasses #-} -- for Vector instances only
+{-# LANGUAGE PatternGuards #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RoleAnnotations #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+= Summary
+
+In this module we provide data types for performing arithmetic with
+physical quantities and units. Information about the physical
+dimensions of the quantities/units is embedded in their types and
+the validity of operations is verified by the type checker at compile
+time. The boxing and unboxing of numerical values as quantities is
+done by multiplication and division of units, of which an incomplete
+set is provided.
+
+We limit ourselves to \"Newtonian\" physics. We do not attempt to
+accommodate relativistic physics in which e.g. addition of length
+and time would be valid.
+
+As far as possible and/or practical the conventions and guidelines
+of NIST's "Guide for the Use of the International System of Units
+(SI)" <#note1 [1]> are followed. Occasionally we will reference specific
+sections from the guide and deviations will be explained.
+
+== Disclaimer
+
+Merely an engineer, the author doubtlessly uses a language and
+notation that makes mathematicians and physicist cringe. He does
+not mind constructive criticism (or pull requests).
+
+The sets of functions and units defined herein are incomplete and
+reflect only the author's needs to date. Again, patches are welcome.
+
+= Usage
+
+== Preliminaries
+
+This module requires GHC 7.8 or later. We utilize Data Kinds, TypeNats,
+Closed Type Families, etc. Clients of the module are generally not
+required to use these extensions.
+
+Clients probably will want to use the NegativeLiterals extension.
+
+== Examples
+
+We have defined operators and units that allow us to define and
+work with physical quantities. A physical quantity is defined by
+multiplying a number with a unit (the type signature is optional).
+
+> v :: Velocity Prelude.Double
+> v = 90 *~ (kilo meter / hour)
+
+It follows naturally that the numerical value of a quantity is
+obtained by division by a unit.
+
+> numval :: Prelude.Double
+> numval = v /~ (meter / second)
+
+The notion of a quantity as the product of a numerical value and a
+unit is supported by 7.1 "Value and numerical value of a quantity" of
+<#note1 [1]>. While the above syntax is fairly natural it is unfortunate that
+it must violate a number of the guidelines in <#note1 [1]>, in particular 9.3
+"Spelling unit names with prefixes", 9.4 "Spelling unit names obtained
+by multiplication", 9.5 "Spelling unit names obtained by division".
+
+As a more elaborate example of how to use the module we define a
+function for calculating the escape velocity of a celestial body
+<#note2 [2]>.
+
+> escapeVelocity :: (Floating a) => Mass a -> Length a -> Velocity a
+> escapeVelocity m r = sqrt (two * g * m / r)
+>   where
+>       two = 2 *~ one
+>       g = 6.6720e-11 *~ (newton * meter ^ pos2 / kilo gram ^ pos2)
+
+The following is an example GHC session where the above function
+is used to calculate the escape velocity of Earth in kilometer per
+second.
+
+>>> :set +t
+>>> let me = 5.9742e24 *~ kilo gram -- Mass of Earth.
+me :: Quantity DMass GHC.Float.Double
+>>> let re = 6372.792 *~ kilo meter -- Mean radius of Earth.
+re :: Quantity DLength GHC.Float.Double
+>>> let ve = escapeVelocity me re   -- Escape velocity of Earth.
+ve :: Velocity GHC.Float.Double
+>>> ve /~ (kilo meter / second)
+11.184537332296259
+it :: GHC.Float.Double
+
+For completeness we should also show an example of the error messages
+we will get from GHC when performing invalid arithmetic. In the
+best case GHC will be able to use the type synonyms we have defined
+in its error messages.
+
+>>> x = 1 *~ meter + 1 *~ second
+Couldn't match expected type `Pos1' against inferred type `Zero'
+    Expected type: Unit DLength t
+    Inferred type: Unit DTime a
+  In the second argument of `(*~)', namely `second'
+  In the second argument of `(+)', namely `1 *~ second'
+
+In other cases the error messages aren't very friendly.
+
+>>> x = 1 *~ meter / (1 *~ second) + 1 *~ kilo gram
+Couldn't match expected type `Zero'
+    against inferred type `Neg Zero'
+  When using functional dependencies to combine
+    Sub Zero (Pos Zero) (Neg Zero),
+      arising from use of `/' at ...
+    Sub Zero (Pos Zero) Zero,
+      arising from use of `/' at ...
+
+It is the author's experience that the usefullness of the compiler
+error messages is more often than not limited to pinpointing the
+location of errors.
+
+= Notes
+
+== Future work
+
+While there is an insane amount of units in use around the world
+it is reasonable to provide at least all SI units. Units outside
+of SI will most likely be added on an as-needed basis.
+
+There are also plenty of elementary functions to add. The 'Floating'
+class can be used as reference.
+
+Another useful addition would be decent 'Show' and 'Read' instances.
+The 'show' implementation could output the numerical value and the
+unit expressed in (base?) SI units, along the lines of:
+
+> instance (Fractional a, Show a) => Show (Length a)
+>   where show x = show (x /~ meter) ++ " m"
+
+Additional functions could be provided for "showing" with any unit
+and prefix.  The 'read' implementation should be able to read values
+with any unit and prefix. It is not clear to the author how to best
+implement these.
+
+Additional physics models could be implemented. See <#note3 [3]> for ideas.
+
+== Related work
+
+Henning Thielemann numeric prelude has a physical units library,
+however, checking of dimensions is dynamic rather than static.
+Aaron Denney has created a toy example of statically checked
+physical dimensions covering only length and time. HaskellWiki
+has pointers <#note4 [4]> to these.
+
+Also see Samuel Hoffstaetter's blog post <#note5 [5]> which uses techniques
+similar to this library.
+
+Libraries with similar functionality exist for other programming
+languages and may serve as inspiration. The author has found the
+Java library JScience <#note6 [6]> and the Fortress programming language <#note7 [7]>
+particularly noteworthy.
+
+== References
+
+1. #note1# http://physics.nist.gov/Pubs/SP811/
+2. #note2# http://en.wikipedia.org/wiki/Escape_velocity
+3. #note3# http://jscience.org/api/org/jscience/physics/models/package-summary.html
+4. #note4# http://www.haskell.org/haskellwiki/Physical_units
+5. #note5# http://liftm.wordpress.com/2007/06/03/scientificdimension-type-arithmetic-and-physical-units-in-haskell/
+6. #note6# http://jscience.org/
+7. #note7# http://research.sun.com/projects/plrg/fortress.pdf
+
+-}
+
+module Numeric.Units.Dimensional
+  ( 
+    -- * Types
+    -- $types
+    Dimensional,
+    Unit, Quantity,
+    Metricality(..),
+    -- * Physical Dimensions
+    -- $dimensions
+    Dimension (Dim),
+    -- ** Dimension Arithmetic
+    -- $dimension-arithmetic
+    type (*), type (/), type (^), Root, Recip,
+    -- ** Term Level Representation of Dimensions
+    -- $dimension-terms
+    Dimension' (Dim'), HasDimension(..), KnownDimension,
+    -- * Dimensional Arithmetic
+    (*~), (/~),
+    (^), (^/), (**), (*), (/), (+), (-),
+    negate, abs, nroot, sqrt, cbrt,
+    -- ** Transcendental Functions
+    exp, log, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, atan2,
+    -- ** Operations on Collections
+    -- $collections
+    (*~~), (/~~), sum, mean, dimensionlessLength, nFromTo,
+    -- * Dimension Synonyms
+    -- $dimension-synonyms
+    DOne, DLength, DMass, DTime, DElectricCurrent, DThermodynamicTemperature, DAmountOfSubstance, DLuminousIntensity,
+    -- * Quantity Synonyms
+    -- $quantity-synonyms
+    Dimensionless, Length, Mass, Time, ElectricCurrent, ThermodynamicTemperature, AmountOfSubstance, LuminousIntensity,
+    -- * Constants
+    -- $constants
+    _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, pi, tau,
+    -- * Constructing Units
+    siUnit, one, mkUnitR, mkUnitQ, mkUnitZ,
+    -- * Unit Metadata
+    name, exactValue, weaken, strengthen, exactify,
+    -- * Pretty Printing
+    showIn,
+    -- * On 'Functor', and Conversion Between Number Representations
+    -- $functor
+    KnownVariant(dmap), changeRep, changeRepApproximate
+  )
+  where
+
+import Prelude
+  ( Show, Eq(..), Ord, Bounded(..), Num, Fractional, Floating, Real, RealFloat, Functor, fmap
+  , (.), flip, show, (++), fromIntegral, fromInteger, fromRational, error, max, succ
+  , Int, Integer, Integral, ($), uncurry, realToFrac, otherwise, undefined, String
+  )
+import qualified Prelude
+import Numeric.NumType.DK.Integers
+  ( TypeInt (Pos2, Pos3)
+  , pos2, pos3
+  , KnownTypeInt, toNum
+  )
+import Control.Applicative
+import Control.DeepSeq
+import Control.Monad (liftM)
+import Data.Coerce (coerce)
+import Data.Data
+import Data.ExactPi
+import Data.Foldable (Foldable(foldr, foldl'))
+import Data.Maybe
+import Data.Monoid (Monoid(..))
+import Data.Ratio
+import Foreign.Ptr (Ptr, castPtr)
+import Foreign.Storable (Storable(..))
+import GHC.Generics
+import Numeric.Units.Dimensional.Dimensions
+import Numeric.Units.Dimensional.UnitNames hiding ((*), (/), (^), weaken, strengthen)
+import qualified Numeric.Units.Dimensional.UnitNames.Internal as Name
+import Numeric.Units.Dimensional.UnitNames.InterchangeNames (HasInterchangeName(..))
+import Numeric.Units.Dimensional.Variants hiding (type (*))
+import qualified Numeric.Units.Dimensional.Variants as V
+import qualified Data.Vector.Generic.Mutable as M
+import qualified Data.Vector.Generic as G
+import qualified Data.Vector.Unboxed.Base as U
+
+{-
+We will reuse the operators and function names from the Prelude.
+To prevent unpleasant surprises we give operators the same fixity
+as the Prelude.
+-}
+
+infixr 8  ^, ^/, **
+infixl 7  *, /
+infixl 6  +, -
+
+
+{- $types
+Our primary objective is to define a data type that can be used to
+represent (while still differentiating between) units and quantities.
+There are two reasons for consolidating units and quantities in one
+data type. The first being to allow code reuse as they are largely
+subject to the same operations. The second being that it allows
+reuse of operators (and functions) between the two without resorting
+to occasionally cumbersome type classes.
+
+The relationship between (the value of) a 'Quantity', its numerical
+value and its 'Unit' is described in 7.1 "Value and numerical value
+of a quantity" of <#note1 [1]>. In short a 'Quantity' is the product of a
+number and a 'Unit'. We define the '*~' operator as a convenient
+way to declare quantities as such a product.
+
+-}
+
+-- | A physical quantity or unit.
+--
+-- We call this data type 'Dimensional' to capture the notion that the
+-- units and quantities it represents have physical dimensions.
+-- 
+-- The type variable 'a' is the only non-phantom type variable and
+-- represents the numerical value of a quantity or the scale (w.r.t.
+-- SI units) of a unit. For SI units the scale will always be 1. For
+-- non-SI units the scale is the ratio of the unit to the SI unit with
+-- the same physical dimension.
+--
+-- Since 'a' is the only non-phantom type we were able to define
+-- 'Dimensional' as a newtype, avoiding boxing at runtime.
+class KnownVariant (v :: Variant) where
+  -- | A dimensional value, either a 'Quantity' or a 'Unit', parameterized by its 'Dimension' and representation.
+  data Dimensional v :: Dimension -> * -> *
+  extractValue :: Dimensional v d a -> (a, Maybe ExactPi)
+  extractName :: Dimensional v d a -> Maybe (UnitName 'NonMetric)
+  injectValue :: (Maybe (UnitName 'NonMetric)) -> (a, Maybe ExactPi) -> Dimensional v d a
+  -- | Maps over the underlying representation of a dimensional value.
+  -- The caller is responsible for ensuring that the supplied function respects the dimensional abstraction.
+  -- This means that the function must preserve numerical values, or linearly scale them while preserving the origin.
+  dmap :: (a1 -> a2) -> Dimensional v d a1 -> Dimensional v d a2
+
+deriving instance Typeable Dimensional
+
+instance KnownVariant 'DQuantity where
+  newtype Dimensional 'DQuantity d a = Quantity' a
+    deriving (Eq, Ord, Data, Generic, Generic1
+#if MIN_VERSION_base(4,8,0)
+     , Typeable -- GHC 7.8 doesn't support deriving this instance
+#endif
+    )
+  extractValue (Quantity' x) = (x, Nothing)
+  extractName _ = Nothing
+  injectValue _ (x, _) = Quantity' x
+  dmap f (Quantity' x) = Quantity' (f x)
+
+instance (Typeable m) => KnownVariant ('DUnit m) where
+  data Dimensional ('DUnit m) d a = Unit' !(UnitName m) !ExactPi !a
+    deriving (Generic, Generic1
+#if MIN_VERSION_base(4,8,0)
+     , Typeable -- GHC 7.8 doesn't support deriving this instance
+#endif
+    )
+  extractValue (Unit' _ e x) = (x, Just e)
+  extractName (Unit' n _ _) = Just . Name.weaken $ n
+  injectValue (Just n) (x, Just e) | Just n' <- relax n = Unit' n' e x
+                                   | otherwise          = Prelude.error "Shouldn't be reachable. Needed a metric name but got a non-metric one."
+  injectValue _        _ = Prelude.error "Shouldn't be reachable. Needed to name a quantity."
+  dmap f (Unit' n e x) = Unit' n e (f x)
+
+-- | A unit of measurement.
+type Unit (m :: Metricality) = Dimensional ('DUnit m)
+
+-- | A dimensional quantity.
+type Quantity = Dimensional 'DQuantity
+
+-- GHC is somewhat unclear about why, but it won't derive this instance, so we give it explicitly.
+instance (Bounded a) => Bounded (Quantity d a) where
+  minBound = Quantity' minBound
+  maxBound = Quantity' maxBound
+
+instance HasInterchangeName (Unit m d a) where
+  interchangeName (Unit' n _ _) = interchangeName n
+
+-- | Extracts the 'UnitName' of a 'Unit'.
+name :: Unit m d a -> UnitName m
+name (Unit' n _ _) = n
+
+-- | Extracts the exact value of a 'Unit', expressed in terms of the SI coherent derived unit (see 'siUnit') of the same 'Dimension'.
+--
+-- Note that the actual value may in some cases be approximate, for example if the unit is defined by experiment.
+exactValue :: Unit m d a -> ExactPi
+exactValue (Unit' _ e _) = e
+
+-- | Discards potentially unwanted type level information about a 'Unit'.
+weaken :: Unit m d a -> Unit 'NonMetric d a
+weaken (Unit' n e v) = Unit' (Name.weaken n) e v
+
+-- | Attempts to convert a 'Unit' which may or may not be 'Metric' to one
+-- which is certainly 'Metric'.
+strengthen :: Unit m d a -> Maybe (Unit 'Metric d a)
+strengthen (Unit' n e v) | Just n' <- Name.strengthen n = Just $ Unit' n' e v
+                         | otherwise                    = Nothing
+
+-- | Forms the exact version of a 'Unit'.
+exactify :: Unit m d a -> Unit m d ExactPi
+exactify (Unit' n e _) = Unit' n e e
+
+-- Operates on a dimensional value using a unary operation on values, possibly yielding a Unit.
+liftUntyped :: (KnownVariant v, KnownVariant (Weaken v)) => (ExactPi -> ExactPi) -> (a -> a) -> UnitNameTransformer -> (Dimensional v d1 a) -> (Dimensional (Weaken v) d2 a)
+liftUntyped fe f nt x = let (x', e') = extractValue x
+                            n = extractName x
+                            n' = (liftA nt) n
+                         in injectValue n' (f x', fmap fe e')
+
+-- Operates on a dimensional value using a unary operation on values, yielding a Quantity.
+liftUntypedQ :: (KnownVariant v) => (a -> a) -> Dimensional v d1 a -> Quantity d2 a
+liftUntypedQ f x = let (x', _) = extractValue x
+                    in Quantity' (f x')
+
+-- Combines two dimensional values using a binary operation on values, possibly yielding a Unit.
+liftUntyped2 :: (KnownVariant v1, KnownVariant v2, KnownVariant (v1 V.* v2)) => (ExactPi -> ExactPi -> ExactPi) -> (a -> a -> a) -> UnitNameTransformer2 -> Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional (v1 V.* v2) d3 a
+liftUntyped2 fe f nt x1 x2 = let (x1', e1') = extractValue x1
+                                 (x2', e2') = extractValue x2
+                                 n1 = extractName x1
+                                 n2 = extractName x2
+                                 n' = (liftA2 nt) n1 n2
+                              in injectValue n' (f x1' x2', fe <$> e1' <*> e2') 
+
+-- Combines two dimensional values using a binary operation on values, yielding a Quantity.
+liftUntyped2Q :: (KnownVariant v1, KnownVariant v2) => (a -> a -> a) -> Dimensional v1 d1 a -> Dimensional v2 d2 a -> Quantity d3 a
+liftUntyped2Q f x1 x2 = let (x1', _) = extractValue x1
+                            (x2', _) = extractValue x2
+                         in Quantity' (f x1' x2') 
+
+-- | Forms a 'Quantity' by multipliying a number and a unit.
+(*~) :: Num a => a -> Unit m d a -> Quantity d a
+x *~ (Unit' _ _ y) = Quantity' (x Prelude.* y)
+
+-- | Divides a 'Quantity' by a 'Unit' of the same physical dimension, obtaining the
+-- numerical value of the quantity expressed in that unit.
+(/~) :: Fractional a => Quantity d a -> Unit m d a -> a
+(Quantity' x) /~ (Unit' _ _ y) = (x Prelude./ y)
+
+{-
+We give '*~' and '/~' the same fixity as '*' and '/' defined below.
+Note that this necessitates the use of parenthesis when composing
+units using '*' and '/', e.g. "1 *~ (meter / second)".
+-}
+
+infixl 7  *~, /~
+
+{- $dimensions
+The phantom type variable d encompasses the physical dimension of
+a 'Dimensional'. As detailed in <#note5 [5]> there are seven base dimensions,
+which can be combined in integer powers to a given physical dimension.
+We represent physical dimensions as the powers of the seven base
+dimensions that make up the given dimension. The powers are represented
+using NumTypes. For convenience we collect all seven base dimensions
+in a data kind 'Dimension'.
+
+We could have chosen to provide type variables for the seven base
+dimensions in 'Dimensional' instead of creating a new data kind
+'Dimension'. However, that would have made any type signatures involving
+'Dimensional' very cumbersome.  By encompassing the physical dimension
+in a single type variable we can "hide" the cumbersome type arithmetic
+behind convenient type classes as will be seen later.
+
+-}
+
+{- $dimension-synonyms
+Using our 'Dimension' data kind we define some type synonyms for convenience.
+We start with the base dimensions, others can be found in "Numeric.Units.Dimensional.Quantities".
+
+-}
+
+{- $quantity-synonyms
+Using the above type synonyms we can define type synonyms for
+quantities of particular physical dimensions.
+
+Again we limit ourselves to the base dimensions, others can be found in "Numeric.Units.Dimensional.Quantities".
+
+-}
+
+type Dimensionless            = Quantity DOne
+type Length                   = Quantity DLength
+type Mass                     = Quantity DMass
+type Time                     = Quantity DTime
+type ElectricCurrent          = Quantity DElectricCurrent
+type ThermodynamicTemperature = Quantity DThermodynamicTemperature
+type AmountOfSubstance        = Quantity DAmountOfSubstance
+type LuminousIntensity        = Quantity DLuminousIntensity
+
+{- $dimension-arithmetic
+When performing arithmetic on units and quantities the arithmetics
+must be applied to both the numerical values of the Dimensionals
+but also to their physical dimensions. The type level arithmetic
+on physical dimensions is governed by closed type families expressed
+as type operators.
+
+We could provide the 'Mul' and 'Div' classes with full functional
+dependencies but that would be of limited utility as there is no
+obvious use for "backwards" type inference and would also limit
+what we can achieve overlapping instances. (In particular, it breaks
+the 'Extensible' module.)
+
+-}
+
+{-
+= Arithmetic on units and quantities =
+
+Thanks to the arithmetic on physical dimensions having been sorted
+out separately a lot of the arithmetic on Dimensionals is straight
+forward. In particular the type signatures are much simplified.
+
+Multiplication, division and powers apply to both units and quantities.
+-}
+
+-- | Multiplies two 'Quantity's or two 'Unit's.
+--
+-- The intimidating type signature captures the similarity between these operations
+-- and ensures that composite 'Unit's are 'NonMetric'.
+(*) :: (KnownVariant v1, KnownVariant v2, KnownVariant (v1 V.* v2), Num a) => Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional (v1 V.* v2) (d1 * d2) a
+(*) = liftUntyped2 (Prelude.*) (Prelude.*) (Name.*)
+
+-- | Divides one 'Quantity' by another or one 'Unit' by another.
+--
+-- The intimidating type signature captures the similarity between these operations
+-- and ensures that composite 'Unit's are 'NotPrefixable'.
+(/) :: (KnownVariant v1, KnownVariant v2, KnownVariant (v1 V.* v2), Fractional a) => Dimensional v1 d1 a -> Dimensional v2 d2 a -> Dimensional (v1 V.* v2) (d1 / d2) a
+(/) = liftUntyped2 (Prelude./) (Prelude./) (Name./)
+
+-- | Raises a 'Quantity' or 'Unit' to an integer power.
+--
+-- Because the power chosen impacts the 'Dimension' of the result, it is necessary to supply a type-level representation
+-- of the exponent in the form of a 'Proxy' to some 'TypeInt'. Convenience values 'pos1', 'pos2', 'neg1', ... 
+-- are supplied by the "Numeric.NumType.DK.Integers" module. The most commonly used ones are
+-- also reexported by "Numeric.Units.Dimensional.Prelude".
+--
+-- The intimidating type signature captures the similarity between these operations
+-- and ensures that composite 'Unit's are 'NotPrefixable'.
+(^) :: (Fractional a, KnownTypeInt i, KnownVariant v, KnownVariant (Weaken v))
+    => Dimensional v d1 a -> Proxy i -> Dimensional (Weaken v) (d1 ^ i) a
+x ^ n = let n' = (toNum n) :: Int
+         in liftUntyped (Prelude.^^ n') (Prelude.^^ n') (Name.^ n') x
+
+{-
+A special case is that dimensionless quantities are not restricted
+to integer exponents. This is accommodated by the '**' operator
+defined later.
+
+
+= Quantity operations =
+
+Some additional operations obviously only make sense for quantities.
+Of these, negation, addition and subtraction are particularly simple
+as they are done in a single physical dimension.
+-}
+
+-- | Negates the value of a 'Quantity'.
+negate :: Num a => Quantity d a -> Quantity d a
+negate = liftUntypedQ Prelude.negate
+
+-- | Adds two 'Quantity's.
+(+) :: Num a => Quantity d a -> Quantity d a -> Quantity d a
+(+) = liftUntyped2Q (Prelude.+)
+
+-- | Subtracts one 'Quantity' from another.
+(-) :: Num a => Quantity d a -> Quantity d a -> Quantity d a
+x - y = x + negate y
+
+-- | Takes the absolute value of a 'Quantity'.
+abs :: Num a => Quantity d a -> Quantity d a
+abs = liftUntypedQ Prelude.abs
+
+{-
+Roots of arbitrary (integral) degree. Appears to occasionally be useful
+for units as well as quantities.
+-}
+
+-- | Computes the nth root of a 'Quantity' using 'Prelude.**'.
+-- 
+-- The 'Root' type family will prevent application of this operator where the result would have a fractional dimension or where n is zero.
+--
+-- Because the root chosen impacts the 'Dimension' of the result, it is necessary to supply a type-level representation
+-- of the root in the form of a 'Proxy' to some 'TypeInt'. Convenience values 'pos1', 'pos2', 'neg1', ... 
+-- are supplied by the "Numeric.NumType.DK.Integers" module. The most commonly used ones are
+-- also reexported by "Numeric.Units.Dimensional.Prelude".
+--
+-- Also available in operator form, see '^/'.
+nroot :: (KnownTypeInt n, Floating a)
+      => Proxy n -> Quantity d a -> Quantity (Root d n) a
+nroot n = let n' = 1 Prelude./ toNum n
+           in liftUntypedQ (Prelude.** n')
+
+{-
+We provide short-hands for the square and cubic roots.
+-}
+
+-- | Computes the square root of a 'Quantity' using 'Prelude.**'.
+--
+-- The 'Root' type family will prevent application where the supplied quantity does not have a square dimension.
+--
+-- prop> sqrt x == nroot pos2 x
+sqrt :: Floating a => Quantity d a -> Quantity (Root d 'Pos2) a
+sqrt = nroot pos2
+
+-- | Computes the cube root of a 'Quantity' using 'Prelude.**'.
+--
+-- The 'Root' type family will prevent application where the supplied quantity does not have a cubic dimension.
+--
+-- prop> cbrt x == nroot pos3 x
+cbrt :: Floating a => Quantity d a -> Quantity (Root d 'Pos3) a
+cbrt = nroot pos3
+
+{-
+We also provide an operator alternative to nroot for those that
+prefer such.
+-}
+
+-- | Computes the nth root of a 'Quantity' using 'Prelude.**'.
+-- 
+-- The 'Root' type family will prevent application of this operator where the result would have a fractional dimension or where n is zero.
+--
+-- Because the root chosen impacts the 'Dimension' of the result, it is necessary to supply a type-level representation
+-- of the root in the form of a 'Proxy' to some 'TypeInt'. Convenience values 'pos1', 'pos2', 'neg1', ... 
+-- are supplied by the "Numeric.NumType.DK.Integers" module. The most commonly used ones are
+-- also reexported by "Numeric.Units.Dimensional.Prelude".
+--
+-- Also available in prefix form, see 'nroot'.
+(^/) :: (KnownTypeInt n, Floating a)
+     => Quantity d a -> Proxy n -> Quantity (Root d n) a
+(^/) = flip nroot
+
+{-
+Since quantities form a monoid under addition, but not under multiplication unless they are dimensionless,
+we will define a monoid instance that adds.
+-}
+
+-- | 'Quantity's of a given 'Dimension' form a 'Monoid' under addition.
+instance (Num a) => Monoid (Quantity d a) where
+  mempty = _0
+  mappend = (+)
+
+{- $collections
+Here we define operators and functions to make working with homogenuous
+lists of dimensionals more convenient.
+
+We define two convenience operators for applying units to all
+elements of a functor (e.g. a list).
+-}
+
+-- | Applies '*~' to all values in a functor.
+(*~~) :: (Functor f, Num a) => f a -> Unit m d a -> f (Quantity d a)
+xs *~~ u = fmap (*~ u) xs
+
+-- | Applies '/~' to all values in a functor.
+(/~~) :: (Functor f, Fractional a) => f (Quantity d a) -> Unit m d a -> f a
+xs /~~ u = fmap (/~ u) xs
+
+infixl 7  *~~, /~~
+
+-- | The sum of all elements in a list.
+sum :: (Num a, Foldable f) => f (Quantity d a) -> Quantity d a
+sum = foldr (+) _0
+
+-- | The arithmetic mean of all elements in a list.
+mean :: (Fractional a, Foldable f) => f (Quantity d a) -> Quantity d a
+mean = uncurry (/) . foldr accumulate (_0, _0)
+  where
+    accumulate val (accum, count) = (accum + val, count + _1)
+
+-- | The length of the foldable data structure as a 'Dimensionless'.
+-- This can be useful for purposes of e.g. calculating averages.
+dimensionlessLength :: (Num a, Foldable f) => f (Dimensional v d a) -> Dimensionless a
+dimensionlessLength x = (fromIntegral $ length x) *~ one
+  where
+    -- As in base-4.8 Data.Foldable for GHC 7.8 (base-4.6) compatibility.
+    -- Once base-4.6. compatibility is abandoned this where clause can
+    -- be deleted (and imports adjusted).
+    length :: Foldable t => t a -> Int
+    length = foldl' (\c _ -> c Prelude.+ 1) 0 
+
+-- | Returns a list of quantities between given bounds.
+nFromTo :: (Fractional a, Integral b) => Quantity d a -- ^ The initial value.
+                                      -> Quantity d a -- ^ The final value.
+                                      -> b -- ^ The number of intermediate values. If less than one, no intermediate values will result.
+                                      -> [Quantity d a]
+nFromTo xi xf n = fmap f [0..n'] ++ [xf]
+  where
+    n' = max 0 n
+    f i = xi + realToFrac (i % succ n') *~ one * (xf - xi)
+
+{-
+
+= Dimensionless =
+
+For dimensionless quantities pretty much any operation is applicable.
+We provide this freedom by making 'Dimensionless' an instance of
+'Functor'.
+-}
+
+instance Functor Dimensionless where
+  fmap = dmap
+
+{-
+We continue by defining elementary functions on 'Dimensionless'
+that may be obviously useful.
+-}
+
+exp, log, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh
+  :: Floating a => Dimensionless a -> Dimensionless a
+exp   = fmap Prelude.exp
+log   = fmap Prelude.log
+sin   = fmap Prelude.sin
+cos   = fmap Prelude.cos
+tan   = fmap Prelude.tan
+asin  = fmap Prelude.asin
+acos  = fmap Prelude.acos
+atan  = fmap Prelude.atan
+sinh  = fmap Prelude.sinh
+cosh  = fmap Prelude.cosh
+tanh  = fmap Prelude.tanh
+asinh = fmap Prelude.asinh
+acosh = fmap Prelude.acosh
+atanh = fmap Prelude.atanh
+
+-- | Raises a dimensionless quantity to a floating power using 'Prelude.**'.
+(**) :: Floating a => Dimensionless a -> Dimensionless a -> Dimensionless a
+(**) = liftUntyped2Q (Prelude.**)
+
+-- | The standard two argument arctangent function.
+-- Since it interprets its two arguments in comparison with one another, the input may have any dimension.
+atan2 :: (RealFloat a) => Quantity d a -> Quantity d a -> Dimensionless a
+atan2 = liftUntyped2Q Prelude.atan2
+
+-- | A polymorphic 'Unit' which can be used in place of the coherent
+-- SI base unit of any dimension. This allows polymorphic quantity
+-- creation and destruction without exposing the 'Dimensional' constructor.
+siUnit :: forall d a.(KnownDimension d, Num a) => Unit 'NonMetric d a
+siUnit = Unit' (baseUnitName $ dimension (Proxy :: Proxy d)) 1 1
+
+{-
+The only unit we will define in this module is 'one'.
+-}
+
+-- | The unit 'one' has dimension 'DOne' and is the base unit of dimensionless values. 
+--
+-- As detailed in 7.10 "Values of quantities expressed simply as numbers:
+-- the unit one, symbol 1" of <#note1 [1]> the unit one generally does not
+-- appear in expressions. However, for us it is necessary to use 'one'
+-- as we would any other unit to perform the "boxing" of dimensionless values.
+one :: Num a => Unit 'NonMetric DOne a
+one = Unit' nOne 1 1
+
+{- $constants
+For convenience we define some constants for small integer values
+that often show up in formulae. We also throw in 'pi' and 'tau' for
+good measure.
+
+-}
+
+-- | The constant for zero is polymorphic, allowing
+-- it to express zero 'Length' or 'Capacitance' or 'Velocity' etc, in addition
+-- to the 'Dimensionless' value zero.
+_0 :: Num a => Quantity d a
+_0 = Quantity' 0
+
+_1, _2, _3, _4, _5, _6, _7, _8, _9 :: (Num a) => Dimensionless a
+_1 = 1 *~ one
+_2 = 2 *~ one
+_3 = 3 *~ one
+_4 = 4 *~ one
+_5 = 5 *~ one
+_6 = 6 *~ one
+_7 = 7 *~ one
+_8 = 8 *~ one
+_9 = 9 *~ one
+
+pi :: Floating a => Dimensionless a
+pi = Prelude.pi *~ one
+
+-- | Twice 'pi'.
+--
+-- For background on 'tau' see http://tauday.com/tau-manifesto (but also
+-- feel free to review http://www.thepimanifesto.com).
+tau :: Floating a => Dimensionless a
+tau = _2 * pi
+
+{- $functor
+We intentionally decline to provide a 'Functor' instance for 'Dimensional' because its use breaks the
+abstraction of physical dimensions.
+
+If you feel your work requires this instance, it is provided as an orphan in "Numeric.Units.Dimensional.Functor".
+
+-}
+
+-- | Convenient conversion between numerical types while retaining dimensional information.
+changeRep :: (KnownVariant v, Real a, Fractional b) => Dimensional v d a -> Dimensional v d b
+changeRep = dmap realToFrac
+
+-- | Convenient conversion from exactly represented values while retaining dimensional information.
+changeRepApproximate :: (KnownVariant v, Floating b) => Dimensional v d ExactPi -> Dimensional v d b
+changeRepApproximate = dmap approximateValue
+
+{- $dimension-terms
+To facilitate parsing and pretty-printing functions that may wish to operate on term-level representations of dimension,
+we provide a means for converting from type-level dimensions to term-level dimensions.
+
+-}
+
+instance (KnownDimension d) => HasDimension (Dimensional v d a) where
+  dimension _ = dimension (Proxy :: Proxy d)
+
+{-
+We will conclude by providing a reasonable 'Show' instance for
+quantities. The SI unit of the quantity is inferred
+from its dimension.
+-}
+instance (KnownDimension d, Show a, Fractional a) => Show (Quantity d a) where
+  show = showIn siUnit
+
+-- | Shows the value of a 'Quantity' expressed in a specified 'Unit' of the same 'Dimension'.
+showIn :: (KnownDimension d, Show a, Fractional a) => Unit m d a -> Quantity d a -> String
+showIn (Unit' n _ y) (Quantity' x) | Name.weaken n == nOne = show (x Prelude./ y)
+                                   | otherwise             = (show (x Prelude./ y)) ++ " " ++ (show n)
+
+instance (KnownDimension d, Show a) => Show (Unit m d a) where
+  show (Unit' n e x) = "The unit " ++ show n ++ ", with value " ++ show e ++ " (or " ++ show x ++ ")"
+
+-- | Forms a new atomic 'Unit' by specifying its 'UnitName' and its definition as a multiple of another 'Unit'.
+-- 
+-- Use this variant when the scale factor of the resulting unit is irrational or 'Approximate'. See 'mkUnitQ' for when it is rational
+-- and 'mkUnitZ' for when it is an integer.
+--
+-- Note that supplying zero as a definining quantity is invalid, as the library relies
+-- upon units forming a group under multiplication.
+-- 
+-- Supplying negative defining quantities is allowed and handled gracefully, but is discouraged
+-- on the grounds that it may be unexpected by other readers.
+mkUnitR :: Floating a => UnitName m -> ExactPi -> Unit m1 d a -> Unit m d a
+mkUnitR n s' (Unit' _ s x) | isExactZero s = error "Supplying zero as a conversion factor is not valid."
+                           | otherwise     = Unit' n (s' Prelude.* s) (approximateValue s' Prelude.* x)
+
+-- | Forms a new atomic 'Unit' by specifying its 'UnitName' and its definition as a multiple of another 'Unit'.
+--
+-- Use this variant when the scale factor of the resulting unit is rational. See 'mkUnitZ' for when it is an integer
+-- and 'mkUnitR' for the general case.
+--
+-- For more information see 'mkUnitR'.
+mkUnitQ :: Fractional a => UnitName m -> Rational -> Unit m1 d a -> Unit m d a
+mkUnitQ n s' (Unit' _ s _) | s' == 0                       = error "Supplying zero as a conversion factor is not valid."
+                           | Just q <- toExactRational s'' = Unit' n s'' (fromRational q)
+                           | otherwise                     = error "The resulting conversion factor is not an exact rational." 
+  where
+    s'' = fromRational s' Prelude.* s                               
+
+-- | Forms a new atomic 'Unit' by specifying its 'UnitName' and its definition as a multiple of another 'Unit'.
+--
+-- Use this variant when the scale factor of the resulting unit is an integer. See 'mkUnitQ' for when it is rational
+-- and 'mkUnitR' for the general case.
+--
+-- For more information see 'mkUnitR'.
+mkUnitZ :: Num a => UnitName m -> Integer -> Unit m1 d a -> Unit m d a
+mkUnitZ n s' (Unit' _ s _) | s' == 0                      = error "Supplying zero as a conversion factor is not valid."
+                           | Just z <- toExactInteger s'' = Unit' n s'' (fromInteger z)
+                           | otherwise                    = error "The resulting conversion factor is not an exact integer."
+  where
+    s'' = fromInteger s' Prelude.* s
+
+instance NFData a => NFData (Quantity d a) -- instance is derived from Generic instance
+
+instance Storable a => Storable (Quantity d a) where
+  sizeOf _ = sizeOf (undefined::a)
+  {-# INLINE sizeOf #-}
+  alignment _ = alignment (undefined::a)
+  {-# INLINE alignment #-}
+  poke ptr = poke (castPtr ptr :: Ptr a) . coerce
+  {-# INLINE poke #-}
+  peek ptr = liftM Quantity' (peek (castPtr ptr :: Ptr a))
+  {-# INLINE peek #-}
+
+{-
+Instances for vectors of quantities.
+-}
+newtype instance U.Vector (Quantity d a)    =  V_Quantity {unVQ :: U.Vector a}
+newtype instance U.MVector s (Quantity d a) = MV_Quantity {unMVQ :: U.MVector s a}
+instance U.Unbox a => U.Unbox (Quantity d a)
+
+instance (M.MVector U.MVector a) => M.MVector U.MVector (Quantity d a) where
+  basicLength          = M.basicLength . unMVQ
+  {-# INLINE basicLength #-}
+  basicUnsafeSlice m n = MV_Quantity . M.basicUnsafeSlice m n . unMVQ
+  {-# INLINE basicUnsafeSlice #-}
+  basicOverlaps u v    = M.basicOverlaps (unMVQ u) (unMVQ v)
+  {-# INLINE basicOverlaps #-}
+  basicUnsafeNew       = liftM MV_Quantity . M.basicUnsafeNew
+  {-# INLINE basicUnsafeNew #-}
+  basicUnsafeRead v    = liftM Quantity' . M.basicUnsafeRead (unMVQ v)
+  {-# INLINE basicUnsafeRead #-}
+  basicUnsafeWrite v i = M.basicUnsafeWrite (unMVQ v) i . coerce
+  {-# INLINE basicUnsafeWrite #-}
+#if MIN_VERSION_vector(0,11,0)
+  basicInitialize      = M.basicInitialize . unMVQ
+  {-# INLINE basicInitialize #-}
+#endif
+
+instance (G.Vector U.Vector a) => G.Vector U.Vector (Quantity d a) where
+  basicUnsafeFreeze    = liftM V_Quantity  . G.basicUnsafeFreeze . unMVQ
+  {-# INLINE basicUnsafeFreeze #-}
+  basicUnsafeThaw      = liftM MV_Quantity . G.basicUnsafeThaw   . unVQ
+  {-# INLINE basicUnsafeThaw #-}
+  basicLength          = G.basicLength . unVQ
+  {-# INLINE basicLength #-}
+  basicUnsafeSlice m n = V_Quantity . G.basicUnsafeSlice m n . unVQ
+  {-# INLINE basicUnsafeSlice #-}
+  basicUnsafeIndexM v  = liftM Quantity' . G.basicUnsafeIndexM (unVQ v)
+  {-# INLINE basicUnsafeIndexM #-}
diff --git a/src/Numeric/Units/Dimensional/Dimensions.hs b/src/Numeric/Units/Dimensional/Dimensions.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/Dimensions.hs
@@ -0,0 +1,25 @@
+{- |
+   Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+Provides both term-level and type-level representations for physical dimensions in 
+a single import for convenience.
+
+Presuming that users intend to work primarily with type level dimensions, this module hides
+arithmetic operators over term level dimensions and aliases for the base term-level dimensions
+to avoid namespace pollution. These features are available directly from
+"Numeric.Units.Dimensional.Dimensions.TermLevel" if desired.
+-}
+module Numeric.Units.Dimensional.Dimensions
+(
+  module Numeric.Units.Dimensional.Dimensions.TermLevel,
+  module Numeric.Units.Dimensional.Dimensions.TypeLevel
+)
+where
+
+import Numeric.Units.Dimensional.Dimensions.TermLevel hiding ((*), (/), (^), recip, dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity)
+import Numeric.Units.Dimensional.Dimensions.TypeLevel
diff --git a/src/Numeric/Units/Dimensional/Dimensions/TermLevel.hs b/src/Numeric/Units/Dimensional/Dimensions/TermLevel.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/Dimensions/TermLevel.hs
@@ -0,0 +1,95 @@
+{-# OPTIONS_HADDOCK not-home, show-extensions #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+This module defines physical dimensions expressed in terms of
+the SI base dimensions, including arithmetic.
+
+-}
+module Numeric.Units.Dimensional.Dimensions.TermLevel
+(
+  -- * Type
+  Dimension'(..),
+  -- * Access to Dimension of Dimensional Values
+  HasDimension(..),
+  -- * Dimension Arithmetic
+  (*), (/), (^), recip,
+  -- * Synonyms for Base Dimensions
+  dOne,
+  dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity,
+  -- * Deconstruction
+  asList
+)
+where
+
+import Data.Monoid (Monoid(..))
+import Prelude (id, (+), (-), Int, Show, Eq, Ord)
+import qualified Prelude as P
+
+-- | A physical dimension, encoded as 7 integers, representing a factorization of the dimension into the
+-- 7 SI base dimensions. By convention they are stored in the same order as 
+-- in the 'Numeric.Units.Dimensional.Dimensions.TypeLevel.Dimension' data kind.
+data Dimension' = Dim' !Int !Int !Int !Int !Int !Int !Int 
+  deriving (Show, Eq, Ord)
+
+-- | The monoid of dimensions under multiplication.
+instance Monoid Dimension' where
+  mempty = dOne
+  mappend = (*)
+
+-- | Dimensional values inhabit this class, which allows access to a term-level representation of their dimension.
+class HasDimension a where 
+  -- | Obtains a term-level representation of a value's dimension.
+  dimension :: a -> Dimension'
+
+instance HasDimension Dimension' where
+  dimension = id
+
+-- | The dimension of dimensionless values.
+dOne :: Dimension'
+dOne = Dim' 0 0 0 0 0 0 0
+
+dLength, dMass, dTime, dElectricCurrent, dThermodynamicTemperature, dAmountOfSubstance, dLuminousIntensity :: Dimension'
+dLength                   = Dim' 1 0 0 0 0 0 0
+dMass                     = Dim' 0 1 0 0 0 0 0
+dTime                     = Dim' 0 0 1 0 0 0 0
+dElectricCurrent          = Dim' 0 0 0 1 0 0 0
+dThermodynamicTemperature = Dim' 0 0 0 0 1 0 0
+dAmountOfSubstance        = Dim' 0 0 0 0 0 1 0
+dLuminousIntensity        = Dim' 0 0 0 0 0 0 1
+
+{-
+We will reuse the operators and function names from the Prelude.
+To prevent unpleasant surprises we give operators the same fixity
+as the Prelude.
+-}
+
+infixr 8  ^
+infixl 7  *, /
+
+-- | Forms the product of two dimensions.
+(*) :: Dimension' -> Dimension' -> Dimension'
+(Dim' l m t i th n j) * (Dim' l' m' t' i' th' n' j') = Dim' (l + l') (m + m') (t + t') (i + i') (th + th') (n + n') (j + j')
+
+-- | Forms the quotient of two dimensions.
+(/) :: Dimension' -> Dimension' -> Dimension'
+(Dim' l m t i th n j) / (Dim' l' m' t' i' th' n' j') = Dim' (l - l') (m - m') (t - t') (i - i') (th - th') (n - n') (j - j')
+
+-- | Raises a dimension to an integer power.
+(^) :: Dimension' -> Int -> Dimension'
+(Dim' l m t i th n j) ^ x = Dim' (x P.* l) (x P.* m) (x P.* t) (x P.* i) (x P.* th) (x P.* n) (x P.* j)
+
+-- | Forms the reciprocal of a dimension.
+recip :: Dimension' -> Dimension'
+recip = (dOne /)
+
+-- | Converts a dimension to a list of 7 integers, representing the exponent associated with each
+-- of the 7 SI base dimensions in the standard order.
+asList :: Dimension' -> [Int]
+asList (Dim' l m t i th n j) = [l, m, t, i, th, n, j]
diff --git a/src/Numeric/Units/Dimensional/Dimensions/TypeLevel.hs b/src/Numeric/Units/Dimensional/Dimensions/TypeLevel.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/Dimensions/TypeLevel.hs
@@ -0,0 +1,146 @@
+{-# OPTIONS_HADDOCK not-home, show-extensions #-}
+
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+This module defines type-level physical dimensions expressed in terms of
+the SI base dimensions using 'Numeric.NumType.DK.NumType' for type-level integers.
+
+Type-level arithmetic, synonyms for the base dimensions, and conversion to the term-level are included.
+-}
+module Numeric.Units.Dimensional.Dimensions.TypeLevel
+(
+  -- * Kind of Type-Level Dimensions
+  type Dimension(..),
+  -- * Dimension Arithmetic
+  type (*), type (/), type (^), type Recip, type Root,
+  -- * Synonyms for Base Dimensions
+  DOne,
+  DLength, DMass, DTime, DElectricCurrent, DThermodynamicTemperature, DAmountOfSubstance, DLuminousIntensity,
+  -- * Conversion to Term Level
+  type KnownDimension
+)
+where
+
+import Data.Proxy
+import Numeric.NumType.DK.Integers
+  ( TypeInt (Zero, Pos1), (+)(), (-)()
+  , KnownTypeInt, toNum
+  )
+import qualified Numeric.NumType.DK.Integers as N
+import Numeric.Units.Dimensional.Dimensions.TermLevel
+
+-- | Represents a physical dimension in the basis of the 7 SI base dimensions, 
+-- where the respective dimensions are represented by type variables
+-- using the following convention.
+--
+--  * l: Length
+--  * m: Mass
+--  * t: Time
+--  * i: Electric current
+--  * th: Thermodynamic temperature
+--  * n: Amount of substance
+--  * j: Luminous intensity
+--
+-- For the equivalent term-level representation, see 'Dimension''
+data Dimension = Dim TypeInt TypeInt TypeInt TypeInt TypeInt TypeInt TypeInt
+
+-- | The type-level dimensions of dimensionless values.
+type DOne                      = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+type DLength                   = 'Dim 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+type DMass                     = 'Dim 'Zero 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+type DTime                     = 'Dim 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero 'Zero
+type DElectricCurrent          = 'Dim 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+type DThermodynamicTemperature = 'Dim 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero 'Zero
+type DAmountOfSubstance        = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
+type DLuminousIntensity        = 'Dim 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+
+{-
+We will reuse the operators and function names from the Prelude.
+To prevent unpleasant surprises we give operators the same fixity
+as the Prelude.
+-}
+
+infixr 8  ^
+infixl 7  *, /
+
+-- | Multiplication of dimensions corresponds to adding of the base
+-- dimensions' exponents.
+type family (a::Dimension) * (b::Dimension) where
+  DOne * d = d
+  d * DOne = d
+  ('Dim l  m  t  i  th  n  j) * ('Dim l' m' t' i' th' n' j')
+    = 'Dim (l + l') (m + m') (t + t') (i + i') (th + th') (n + n') (j + j')
+
+-- | Division of dimensions corresponds to subtraction of the base
+-- dimensions' exponents.
+type family (a::Dimension) / (d::Dimension) where
+  d / DOne = d
+  d / d = DOne
+  ('Dim l  m  t  i  th  n  j) / ('Dim l' m' t' i' th' n' j')
+    = 'Dim (l - l') (m - m') (t - t') (i - i') (th - th') (n - n') (j - j')
+
+-- | The reciprocal of a dimension is defined as the result of dividing 'DOne' by it,
+-- or of negating each of the base dimensions' exponents.
+type Recip (d :: Dimension) = DOne / d
+
+-- | Powers of dimensions corresponds to multiplication of the base
+-- dimensions' exponents by the exponent.
+-- 
+-- We limit ourselves to integer powers of Dimensionals as fractional
+-- powers make little physical sense.
+type family (d::Dimension) ^ (x::TypeInt) where
+  DOne ^ x = DOne
+  d ^ 'Zero = DOne
+  d ^ 'Pos1 = d
+  ('Dim l  m  t  i  th  n  j) ^ x
+    = 'Dim (l N.* x) (m N.* x) (t N.* x) (i N.* x) (th N.* x) (n N.* x) (j N.* x)
+
+-- | Roots of dimensions corresponds to division of the base dimensions'
+-- exponents by the order(?) of the root.
+-- 
+-- See 'sqrt', 'cbrt', and 'nroot' for the corresponding term-level operations.
+type family Root (d::Dimension) (x::TypeInt) where
+  Root DOne x = DOne
+  Root d 'Pos1 = d
+  Root ('Dim l  m  t  i  th  n  j) x
+    = 'Dim (l N./ x) (m N./ x) (t N./ x) (i N./ x) (th N./ x) (n N./ x) (j N./ x)
+
+-- | A KnownDimension is one for which we can construct a term-level representation.
+-- Each validly constructed type of kind 'Dimension' has a 'KnownDimension' instance.
+--
+-- While 'KnownDimension' is a constraint synonym, the presence of @'KnownDimension' d@ in
+--  a context allows use of @'dimension' :: 'Proxy' d -> 'Dimension''@.
+type KnownDimension (d :: Dimension) = HasDimension (Proxy d)
+
+instance ( KnownTypeInt l
+         , KnownTypeInt m
+         , KnownTypeInt t
+         , KnownTypeInt i
+         , KnownTypeInt th
+         , KnownTypeInt n
+         , KnownTypeInt j
+         ) => HasDimension (Proxy ('Dim l m t i th n j))
+  where 
+    dimension _ = Dim'
+                (toNum (Proxy :: Proxy l))
+                (toNum (Proxy :: Proxy m))
+                (toNum (Proxy :: Proxy t))
+                (toNum (Proxy :: Proxy i))
+                (toNum (Proxy :: Proxy th))
+                (toNum (Proxy :: Proxy n))
+                (toNum (Proxy :: Proxy j))
diff --git a/src/Numeric/Units/Dimensional/Dynamic.hs b/src/Numeric/Units/Dimensional/Dynamic.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/Dynamic.hs
@@ -0,0 +1,74 @@
+{- |
+    Copyright  : Copyright (C) 2006-2014 Bjorn Buckwalter
+    License    : BSD3
+
+    Maintainer : bjorn@buckwalter.se
+    Stability  : Stable
+    Portability: GHC only?
+
+Defines types for manipulation of units and quantities without phantom types for their dimensions.
+-}
+
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Numeric.Units.Dimensional.Dynamic
+(
+  AnyQuantity
+, demoteQuantity, promoteQuantity
+, AnyUnit
+, demoteUnit, promoteUnit
+) where
+
+import Numeric.Units.Dimensional.Prelude hiding (lookup)
+import Numeric.Units.Dimensional.UnitNames (UnitName, baseUnitName)
+import Data.ExactPi
+import Data.Proxy
+
+-- | A 'Quantity' whose 'Dimension' is only known dynamically.
+data AnyQuantity v = AnyQuantity Dimension' v
+  deriving (Eq)
+
+instance (Show v) => Show (AnyQuantity v) where
+  show (AnyQuantity d v) = (show v) ++ " " ++ (show . baseUnitName $ d)
+
+instance HasDimension (AnyQuantity v) where
+  dimension (AnyQuantity d _) = d
+
+-- | Converts a 'Quantity' of statically known 'Dimension' into an 'AnyQuantity'.
+demoteQuantity :: forall d v.(KnownDimension d, Fractional v) => Quantity d v -> AnyQuantity v
+demoteQuantity val = AnyQuantity dim (val /~ siUnit)
+  where dim = dimension (Proxy :: Proxy d)
+
+-- | Converts an 'AnyQuantity' into a 'Quantity' of statically known 'Dimension', or 'Nothing' if the dimension does not match.
+promoteQuantity :: forall d v.(KnownDimension d, Fractional v) => AnyQuantity v -> Maybe (Quantity d v)
+promoteQuantity (AnyQuantity dim val) | dim == dim' = Just $ val *~ siUnit
+                                      | otherwise   = Nothing
+                                                    where
+                                                      dim' = dimension (Proxy :: Proxy d)
+
+-- | A 'Unit' whose 'Dimension' is only known dynamically.
+data AnyUnit = AnyUnit Dimension' (UnitName 'NonMetric) ExactPi
+
+instance Show AnyUnit where
+  show (AnyUnit _ n e) = "1 " ++ (show n) ++ " =def= " ++ (show e) ++ " of the SI base unit"
+
+instance HasDimension AnyUnit where
+  dimension (AnyUnit d _ _) = d
+
+-- | Converts a 'Unit' of statically known 'Dimension' into an 'AnyUnit'.
+demoteUnit :: forall a d v.(KnownDimension d) => Unit a d v -> AnyUnit
+demoteUnit u = AnyUnit dim (name $ weaken u) (exactValue u)
+  where
+    dim = dimension (Proxy :: Proxy d)
+
+-- | Converts an 'AnyUnit' into a 'Unit' of statically known 'Dimension', or 'Nothing' if the dimension does not match.
+--
+-- The result is represented in 'ExactPi', conversion to other representations is possible using 'changeRepApproximate'.
+promoteUnit :: forall d.(KnownDimension d) => AnyUnit -> Maybe (Unit 'NonMetric d ExactPi)
+promoteUnit (AnyUnit dim n e) | dim == dim' = Just $ mkUnitR n e siUnit
+                              | otherwise   = Nothing
+  where
+    dim' = dimension (Proxy :: Proxy d)
diff --git a/src/Numeric/Units/Dimensional/Functor.hs b/src/Numeric/Units/Dimensional/Functor.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/Functor.hs
@@ -0,0 +1,40 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-# LANGUAGE CPP #-}
+#if MIN_VERSION_base(4,8,0)
+-- OverlappingInstances was deprecated by GHC 7.10 in favor of OVERLAPPING pragmas.
+#else
+{-# LANGUAGE OverlappingInstances #-}
+{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}
+#endif
+
+{- |
+   Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+Provides a 'Functor' instance for 'Dimensional'.
+
+Note that this instance is dubious, because it allows you to break the dimensional abstraction. See 'dmap' for more information.
+ 
+Note that, while this instance overlaps with that given for 'Dimensionless', it is confluent with that instance.
+
+Note that this is an orphan instance.
+-}
+module Numeric.Units.Dimensional.Functor where
+
+import Numeric.Units.Dimensional
+
+-- | A 'Functor' instance for 'Dimensional'.
+--
+-- Note that this instance is dubious, because it allows you to break the dimensional abstraction. See 'dmap' for more information.
+-- 
+-- Note that, while this instance overlaps with that given for 'Dimensionless', it is confluent with that instance.
+--
+-- Note that this is an orphan instance.
+instance {-# OVERLAPPING #-} (KnownVariant v) => Functor (Dimensional v d) where
+  fmap = dmap
diff --git a/src/Numeric/Units/Dimensional/NonSI.hs b/src/Numeric/Units/Dimensional/NonSI.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/NonSI.hs
@@ -0,0 +1,299 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE NumDecimals #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+= Summary
+
+This module defines units that are not part of the SI, with the
+exception of those defined in the "Numeric.Units.Dimensional.SIUnits" module (units outside
+of the SI accepted for use with the SI).
+
+Any chapters, sections or tables referenced are from <#note1 [1]> unless
+otherwise specified.
+
+== Neper, bel, shannon and the like
+
+The units of section 5.1.2 are purposefully (but not permanently)
+omitted. In fact the logarithmic units (see section 8.7) are
+problematic and it is not clear how to implement them. Perhaps with
+a conversion function similar to for degrees Celsius.
+
+= References
+
+1. #note1# http://physics.nist.gov/Pubs/SP811/
+2. #note2# http://www.iau.org/science/publications/proceedings_rules/units/
+3. #note3# http://en.m.wikipedia.org/wiki/Pressure
+4. #note4# http://en.m.wikipedia.org/wiki/Torr
+
+-}
+
+module Numeric.Units.Dimensional.NonSI 
+(
+  -- * Units Defined By Experiment
+  -- $values-obtained-experimentally
+  electronVolt, unifiedAtomicMassUnit, dalton,
+  -- * Standard Gravity
+  -- $standard-gravity
+  gee,
+  -- * Inch-pound Units
+  -- $inch-pound-units
+  inch, foot, mil, poundMass, ounce, poundForce, slug, psi, yard, mile, nauticalMile, knot,
+  revolution, solid, teaspoon, acre,
+  -- * Years
+  -- $year
+  year, century,
+  -- * Pressure Units
+  -- $pressure-units
+  bar, atmosphere, technicalAtmosphere, mmHg, inHg, inHg_UCUM, inHg_NIST, torr,
+  -- * Radiation Units
+  rad,
+  -- * Kinematic Viscosity
+  stokes,
+  -- * Temperature
+  -- $temperature
+  degreeFahrenheit, degreeRankine,
+  -- * Imperial Volumes
+  -- $imperial-volumes
+  imperialGallon, imperialQuart, imperialPint, imperialCup, imperialGill, imperialFluidOunce,
+  -- * US Customary Volumes
+  -- $us-customary-volumes
+  usGallon, usQuart, usPint, usCup, usGill, usFluidOunce
+)
+where
+
+import Data.ExactPi
+import Numeric.Units.Dimensional.Prelude
+import Numeric.Units.Dimensional.UnitNames.Internal (ucumMetric, ucum, dimensionalAtom)
+import qualified Prelude
+
+{- $values-obtained-experimentally
+
+From Table 7, units accepted for use with the SI whose values in SI units are
+obtained experimentally.
+
+When <#note1 [1]> was published the electron volt had a standard combined
+uncertainity of 0.00000049e-19 J and the unified atomic mass unit
+had a combined uncertainty of 0.0000010e-27 kg.
+
+-}
+
+electronVolt :: Floating a => Unit 'Metric DEnergy a
+electronVolt = mkUnitR (ucumMetric "eV" "eV" "electron volt") (Approximate 1.60217733e-19) $ joule
+unifiedAtomicMassUnit :: Floating a => Unit 'Metric DMass a
+unifiedAtomicMassUnit = mkUnitR (ucumMetric "u" "u" "atomic mass unit") (Approximate 1.6605402e-27) $ kilo gram
+dalton :: Floating a => Unit 'Metric DMass a
+dalton = mkUnitR (ucumMetric "eV" "Da" "Dalton") 1 $ unifiedAtomicMassUnit
+
+{- $standard-gravity
+In order to relate e.g. pounds mass to pounds force we define the unit
+'gee' equal to the standard gravity g_0: the nominal acceleration of a
+body in free fall in a vacuum near the surface of the earth (note that
+local values of acceleration due to gravity will differ from the standard
+gravity). I.e. g_0 = 1 gee.
+-}
+
+gee :: Fractional a => Unit 'Metric DAcceleration a
+gee = mkUnitQ (ucumMetric "[g]" "g" "gee") 9.80665 $ meter / second ^ pos2
+
+{- $inch-pound-units
+Some US customary (that is, inch-pound) units.
+-}
+
+inch, foot, mil :: Fractional a => Unit 'NonMetric DLength a
+inch = mkUnitQ (ucum "[in_i]" "in" "inch") 2.54 $ centi meter
+foot = mkUnitQ (ucum "[ft_i]" "ft" "foot") 12 $ inch     -- 0.3048 m
+mil  = mkUnitQ (ucum "[mil_i]" "mil" "mil") 0.001 $ inch
+poundMass, ounce :: Fractional a => Unit 'NonMetric DMass a
+poundMass = mkUnitQ (ucum "[lb_av]" "lb" "pound") 0.45359237 $ kilo gram
+ounce     = mkUnitQ (ucum "[oz_av]" "oz" "ounce") (1 Prelude./ 16) $ poundMass
+
+poundForce :: Fractional a => Unit 'NonMetric DForce a
+poundForce = mkUnitQ (ucum "[lbf_av]" "lbf" "pound force") 1 $ poundMass * gee  -- 4.4482 N
+
+{-
+
+The slug is an alternative unit of mass defined in terms of the pound-force.
+
+-}
+
+slug :: Fractional a => Unit 'NonMetric DMass a
+slug = poundForce * (second^pos2) / foot
+
+{-
+
+Pounds of force per square inch.
+
+-}
+
+psi :: Fractional a => Unit 'NonMetric DPressure a
+psi = mkUnitQ (ucum "[psi]" "psi" "pound per square inch") 1 $ poundForce / inch ^ pos2
+
+{-
+
+= Various other (non inch-pound) units =
+
+-}
+
+yard, mile :: (Fractional a) => Unit 'NonMetric DLength a
+yard = mkUnitQ (ucum "[yd_i]" "yd" "yard") 3 $ foot
+mile = mkUnitQ (ucum "[mi_i]" "mi" "mile") 5280 $ foot
+nauticalMile :: (Num a) => Unit 'NonMetric DLength a
+nauticalMile = mkUnitZ (ucum "[nmi_i]" "NM" "nautical mile") 1852 $ meter
+knot :: (Fractional a) => Unit 'NonMetric DVelocity a
+knot = mkUnitQ (ucum "[kt_i]" "kt" "knot") 1 $ nauticalMile / hour
+revolution :: (Floating a) => Unit 'NonMetric DOne a
+revolution = mkUnitR (dimensionalAtom "rev" "rev" "revolution") (2 Prelude.* Prelude.pi) $ radian
+solid :: (Floating a) => Unit 'NonMetric DOne a
+solid = mkUnitR (dimensionalAtom "solid" "solid" "solid") (4 Prelude.* Prelude.pi) $ steradian
+teaspoon :: (Fractional a) => Unit 'NonMetric DVolume a
+teaspoon = mkUnitQ (ucum "[tsp_m]" "tsp" "teaspoon") 5 $ milli liter
+acre :: (Fractional a) => Unit 'NonMetric DArea a
+acre = mkUnitQ (ucum "[acr_us]" "ac" "acre") 43560 $ square foot
+
+{- $year
+
+The IAU recommends <#note2 [2]> that:
+
+  Although there are several different kinds of year (as there are
+  several kinds of day), it is best to regard a year as a julian
+  year of 365.25 days (31.5576 Ms) unless otherwise specified.
+
+This aligns well with my needs so I'm happy to oblige. We define
+the year in terms of seconds in order to avoid a 'Fractional'
+constraint, and also provide a Julian century.
+
+-}
+
+year, century :: Num a => Unit 'NonMetric DTime a
+year    = mkUnitZ (ucum "a_j" "a" "mean Julian year") 31557600 $ second
+century = mkUnitZ (dimensionalAtom "c_j" "cen" "mean Julian century") 100 $ year
+
+{- $pressure-units
+It seems that nearly every area of application has its own customary unit for measuring pressure.
+We include some of the common ones here. 'psi' was defined earlier.
+-}
+
+-- | The bar is exactly 100,000 'Numeric.Units.Dimensional.SIUnits.pascal'.
+--
+-- From Wikipedia:
+--
+--  It is about equal to the atmospheric pressure on Earth at sea level.
+bar :: (Num a) => Unit 'Metric DPressure a
+bar = mkUnitZ (ucumMetric "bar" "bar" "bar") 1e5 $ pascal
+
+-- | The "standard atmosphere".
+--
+-- From Wikipedia <#note3 [3]>:
+--
+--  The standard atmosphere (atm) is an established constant. It is
+--  approximately equal to typical air pressure at earth mean sea
+--  level.
+atmosphere :: (Num a) => Unit 'NonMetric DPressure a
+atmosphere = mkUnitZ (ucum "atm" "atm" "standard atmosphere") 101325 $ pascal
+
+-- | The "technical atmosphere"
+--
+-- From Wikipedia:
+--
+--  A technical atmosphere (symbol: at) is a non-SI unit of pressure equal
+--  to one kilogram-force per square centimeter.
+technicalAtmosphere :: (Fractional a) => Unit 'NonMetric DPressure a
+technicalAtmosphere = mkUnitQ (ucum "att" "at" "technical atmosphere") 1 $ kilo gram * gee * centi meter ^ neg2
+
+-- | The conventional value for the pressure exerted by a 1 mm high column of mercury.
+--
+-- Per Wikipedia <#note4 [4]>, one mmHg (millimeter of mercury) is defined as:
+--
+--  The pressure exerted at the base of a column of fluid exactly 1 mm high,
+--  when the density of the fluid is exactly 13.5951 g/cm^3, at a place
+--  where the acceleration of gravity is exactly 9.80665 m/s^2.
+
+-- The chosen fluid density approximately corresponds to that of mercury
+-- at 0 deg. Under most conditions, 1 mmHg is approximately equal to 1 'torr'.
+mmHg :: (Floating a) => Unit 'NonMetric DPressure a
+mmHg = milli mHg
+
+mHg :: (Floating a) => Unit 'Metric DPressure a
+mHg = mkUnitR (ucumMetric "m[Hg]" "m Hg" "meter of mercury") (Approximate 133.3220) $ kilo pascal
+
+-- | The conventional value for the pressure exerted by a 1 inch high column of mercury.
+--
+-- Column inches of mercury are also used to measure pressure, especially in
+-- meteorological or aeronautical contexts in the United States.
+--
+-- This is the value defined by UCUM. For the value defined by NIST, see 'inHg_NIST'.
+inHg :: (Floating a) => Unit 'NonMetric DPressure a
+inHg = inHg_UCUM
+
+-- | The conventional value for the pressure exerted by a 1 inch high column of mercury.
+--
+-- Column inches of mercury are also used to measure pressure, especially in
+-- meteorological or aeronautical contexts in the United States.
+--
+-- This is the value defined by UCUM. For the value defined by NIST, see 'inHg_NIST'.
+inHg_UCUM :: (Floating a) => Unit 'NonMetric DPressure a
+inHg_UCUM = mkUnitR (ucum "[in_i'Hg]" "in Hg" "inch of mercury") 1 $ mHg * inch / meter
+
+-- | The conventional value for the pressure exerted by a 1 inch high column of mercury.
+--
+-- Column inches of mercury are also used to measure pressure, especially in
+-- meteorological or aeronautical contexts in the United States.
+--
+-- This is the value defined by NIST. For the value defined by UCUM, see 'inHg_UCUM'.
+inHg_NIST :: (Floating a) => Unit 'NonMetric DPressure a
+inHg_NIST = mkUnitR (dimensionalAtom "[in_i'Hg_NIST]" "in Hg" "inch of mercury") 3.386389 $ pascal
+
+-- | One torr (symbol: Torr) is defined as 1/760 atm, which is approximately equal to 1 'mmHg'.
+torr :: (Fractional a) => Unit 'NonMetric DPressure a
+torr = mkUnitQ (dimensionalAtom "Torr" "Torr" "Torr") (1 Prelude./ 760) $ atmosphere
+
+{- Radiation -}
+rad :: (Fractional a) => Unit 'Metric DAbsorbedDose a
+rad = mkUnitQ (ucumMetric "RAD" "RAD" "RAD") 1 $ centi gray
+
+{- Kinematic Viscosity -}
+stokes :: (Fractional a) => Unit 'Metric DKinematicViscosity a
+stokes = mkUnitQ (ucumMetric "St" "St" "Stokes") 1 $ centi meter ^ pos2 / second
+
+{- $temperature 
+These units of temperature are relative. For absolute temperatures, see 'Numeric.Units.Dimensional.SIUnits.fromDegreeCelsiusAbsolute'.
+-}
+degreeFahrenheit :: (Fractional a) => Unit 'NonMetric DThermodynamicTemperature a
+degreeFahrenheit = mkUnitQ (ucum "[degF]" "°F" "degree Fahrenheit") (5 Prelude./ 9) $ degreeCelsius
+
+degreeRankine :: (Fractional a) => Unit 'NonMetric DThermodynamicTemperature a
+degreeRankine = mkUnitQ (ucum "[degR]" "°R" "degree Rankine") 1 $ degreeFahrenheit
+
+{- $imperial-volumes
+Per http://en.wikipedia.org/wiki/Imperial_units and http://en.wikipedia.org/wiki/Cup_(unit)#Imperial_cup.
+-}
+
+imperialGallon, imperialQuart, imperialPint, imperialCup,
+                imperialGill, imperialFluidOunce
+                :: (Fractional a) => Unit 'NonMetric DVolume a
+imperialGallon     = mkUnitQ (ucum "[gal_br]" "gal" "gallon")         4.54609          $ liter
+imperialQuart      = mkUnitQ (ucum "[qt_br]" "qt" "quart")            (1 Prelude./ 4)  $ imperialGallon
+imperialPint       = mkUnitQ (ucum "[pt_br]" "pt" "pint")             (1 Prelude./ 8)  $ imperialGallon
+imperialCup        = mkUnitQ (dimensionalAtom "[cup_br]" "cup" "cup") 0.5              $ imperialPint
+imperialGill       = mkUnitQ (ucum "[gil_br]" "gill" "gill")          (1 Prelude./ 4)  $ imperialPint
+imperialFluidOunce = mkUnitQ (ucum "[foz_br]" "fl oz" "fluid ounce")  (1 Prelude./ 20) $ imperialPint
+
+{- $us-customary-volumes
+Per http://www.nist.gov/pml/wmd/pubs/upload/2012-hb44-final.pdf page 452 and http://en.wikipedia.org/wiki/United_States_customary_units#Fluid_volume
+Note that there exist rarely-used "dry" variants of units with overlapping names.
+-}
+
+usGallon, usQuart, usPint, usCup, usGill, usFluidOunce :: (Fractional a) => Unit 'NonMetric DVolume a
+usGallon     = mkUnitQ (ucum "[gal_us]" "gal" "gallon")        231              $ (cubic inch)
+usQuart      = mkUnitQ (ucum "[qt_us]" "qt" "quart")           (1 Prelude./ 4)  $ usGallon
+usPint       = mkUnitQ (ucum "[pt_us]" "pt" "pint")            (1 Prelude./ 8)  $ usGallon
+usCup        = mkUnitQ (ucum "[cup_us]" "cup" "cup")           (1 Prelude./ 2)  $ usPint
+usGill       = mkUnitQ (ucum "[gil_us]" "gill" "gill")         (1 Prelude./ 4)  $ usPint
+usFluidOunce = mkUnitQ (ucum "[foz_us]" "fl oz" "fluid ounce") (1 Prelude./ 16) $ usPint -- sic, does not match factor used in imperial system
diff --git a/src/Numeric/Units/Dimensional/Prelude.hs b/src/Numeric/Units/Dimensional/Prelude.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/Prelude.hs
@@ -0,0 +1,47 @@
+{- |
+   Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+= Summary
+
+This module supplies a convenient set of imports for working with the dimensional package, including aliases for common 'Quantity's and 'Dimension's,
+and a comprehensive set of SI units and units accepted for use with the SI.
+
+It re-exports the "Prelude", hiding arithmetic functions whose names collide with the dimensionally-typed versions supplied by this package.
+
+-}
+module Numeric.Units.Dimensional.Prelude
+    ( module Numeric.Units.Dimensional
+    , module Numeric.Units.Dimensional.Quantities
+    , module Numeric.Units.Dimensional.SIUnits
+    , module Numeric.NumType.DK.Integers
+    , module Data.Foldable
+    , module Prelude
+    ) where
+
+import Numeric.Units.Dimensional hiding
+    ( dmap
+    )
+
+import Numeric.Units.Dimensional.Quantities
+
+import Numeric.Units.Dimensional.SIUnits
+
+import Numeric.NumType.DK.Integers
+    ( neg5, neg4, neg3, neg2, neg1, zero, pos1, pos2, pos3, pos4, pos5
+    )  -- Used in exponents.
+
+import Data.Foldable
+    ( product, minimum, maximum )
+
+import Prelude hiding
+    ( (+), (-), (*), (/), (^), (**)
+    , abs, negate, pi, exp, log, sqrt
+    , sin, cos, tan, asin, acos, atan, atan2
+    , sinh, cosh, tanh, asinh, acosh, atanh
+    , sum, product, minimum, maximum
+    )  -- Hide definitions overridden by 'Numeric.Dimensional'.
diff --git a/src/Numeric/Units/Dimensional/Quantities.hs b/src/Numeric/Units/Dimensional/Quantities.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/Quantities.hs
@@ -0,0 +1,426 @@
+{-# OPTIONS_HADDOCK show-extensions #-}
+
+{-# LANGUAGE DataKinds #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+= Summary
+
+This module defines type synonyms for common dimensionalities and
+the associated quantity types. Additional dimensionalities and
+quantity types will be added on an as-needed basis.
+
+The definitions in this module are grouped so that a type synonym
+for the dimensionality is defined first in terms of base dimension
+exponents. Then a type synonym for the corresponding quantity type
+is defined. If there are several quantity types with the same
+dimensionality type synonyms are provided for each quantity type.
+
+= References
+
+1. #note1# http://physics.nist.gov/Pubs/SP811/
+
+-}
+
+module Numeric.Units.Dimensional.Quantities 
+(
+  -- * Quantities from the NIST Guide
+  -- $nist-guide
+  Area, Volume, Velocity, Acceleration, WaveNumber, MassDensity, Density, SpecificVolume, CurrentDensity,
+  MagneticFieldStrength, AmountOfSubstanceConcentration, Concentration, Luminance,
+  -- $table3
+  PlaneAngle, SolidAngle, Frequency, Force, Pressure, Stress, Energy, Work, QuantityOfHeat, Power, RadiantFlux,
+  ElectricCharge, QuantityOfElectricity, ElectricPotential, PotentialDifference, ElectromotiveForce,
+  Capacitance, ElectricResistance, ElectricConductance, MagneticFlux, MagneticFluxDensity,
+  Inductance, LuminousFlux, Illuminance, CelsiusTemperature,
+  Activity, AbsorbedDose, SpecificEnergy, Kerma, DoseEquivalent, AmbientDoseEquivalent, DirectionalDoseEquivalent, PersonalDoseEquivalent, EquivalentDose, CatalyticActivity,
+  -- $table4
+  AngularVelocity, AngularAcceleration, DynamicViscosity, MomentOfForce, SurfaceTension, HeatFluxDensity,
+  Irradiance, RadiantIntensity, Radiance, HeatCapacity, Entropy, SpecificHeatCapacity, SpecificEntropy,
+  ThermalConductivity, EnergyDensity, ElectricFieldStrength, ElectricChargeDensity, ElectricFluxDensity, Permittivity, Permeability,
+  MolarEnergy, MolarEntropy, MolarHeatCapacity, Exposure, AbsorbedDoseRate,
+  -- * Quantities not from the NIST Guide
+  -- $not-nist-guide
+  Impulse, Momentum, MassFlow, VolumeFlow, GravitationalParameter, KinematicViscosity, FirstMassMoment, MomentOfInertia, AngularMomentum,
+  ThermalResistivity, ThermalConductance, ThermalResistance, HeatTransferCoefficient, ThermalAdmittance, ThermalInsulance,
+  Jerk, Angle, Thrust, Torque, EnergyPerUnitMass,
+  -- * Powers of Unit Lengths
+  -- $powers-of-length-units
+  square, cubic,
+  -- * Dimension Aliases
+  -- $dimension-aliases
+  DArea, DVolume, DVelocity, DAcceleration, DWaveNumber, DMassDensity, DDensity, DSpecificVolume, DCurrentDensity,
+  DMagneticFieldStrength, DAmountOfSubstanceConcentration, DConcentration, DLuminance,
+  DPlaneAngle, DSolidAngle, DFrequency, DForce, DPressure, DStress, DEnergy, DWork, DQuantityOfHeat, DPower, DRadiantFlux,
+  DElectricCharge, DQuantityOfElectricity, DElectricPotential, DPotentialDifference, DElectromotiveForce,
+  DCapacitance, DElectricResistance, DElectricConductance, DMagneticFlux, DMagneticFluxDensity,
+  DInductance, DLuminousFlux, DIlluminance, DCelsiusTemperature,
+  DActivity, DAbsorbedDose, DSpecificEnergy, DKerma, DDoseEquivalent, DAmbientDoseEquivalent, DDirectionalDoseEquivalent, DPersonalDoseEquivalent, DEquivalentDose, DCatalyticActivity,
+  DAngularVelocity, DAngularAcceleration, DDynamicViscosity, DMomentOfForce, DSurfaceTension, DHeatFluxDensity,
+  DIrradiance, DRadiantIntensity, DRadiance, DHeatCapacity, DEntropy, DSpecificHeatCapacity, DSpecificEntropy,
+  DThermalConductivity, DEnergyDensity, DElectricFieldStrength, DElectricChargeDensity, DElectricFluxDensity, DPermittivity, DPermeability,
+  DMolarEnergy, DMolarEntropy, DMolarHeatCapacity, DExposure, DAbsorbedDoseRate,
+  DImpulse, DMomentum, DMassFlow, DVolumeFlow, DGravitationalParameter, DKinematicViscosity, DFirstMassMoment, DMomentOfInertia, DAngularMomentum,
+  DThermalResistivity, DThermalConductance, DThermalResistance, DHeatTransferCoefficient, DThermalAdmittance, DThermalInsulance,
+  DJerk, DAngle, DThrust, DTorque, DEnergyPerUnitMass
+)
+where
+
+import Numeric.Units.Dimensional
+  ( Dimension (Dim), Quantity, Dimensionless
+  , DOne, DLuminousIntensity, DThermodynamicTemperature
+  , Unit, DLength, (^)  -- Used only for 'square' and 'cubic'.
+  , Metricality(..)
+  )
+import Numeric.NumType.DK.Integers
+  ( TypeInt (Neg3, Neg2, Neg1, Zero, Pos1, Pos2, Pos3, Pos4)
+  , pos2, pos3  -- Used only for 'square' and 'cubic'.
+  )
+import Prelude (Fractional)
+import Data.Typeable
+
+{- $nist-guide
+The following quantities are all from the NIST publication "Guide
+for the Use of the International System of Units (SI)" <#note1 [1]>. Any
+chapters, sections or tables referenced are from <#note1 [1]> unless otherwise
+specified.
+
+For lack of better organization we provide definitions grouped by
+table in <#note1 [1]>.
+
+== Table 2
+
+"Examples of SI derived units expressed in terms of SI base units."
+
+-}
+
+{- $dimension-aliases
+For each 'Quantity' alias supplied above, we also supply a corresponding 'Dimension' alias.
+
+These dimension aliases may be convenient for supplying type signatures for 'Unit's or for other type-level dimensional programming.
+-}
+
+type DArea = 'Dim 'Pos2 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+type Area  = Quantity DArea
+
+type DVolume = 'Dim 'Pos3 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+type Volume  = Quantity DVolume
+
+type DVelocity = 'Dim 'Pos1 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+type Velocity  = Quantity DVelocity
+
+type DAcceleration = 'Dim 'Pos1 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+type Acceleration  = Quantity DAcceleration
+
+type DWaveNumber = 'Dim 'Neg1 'Zero 'Zero 'Zero 'Zero 'Zero 'Zero
+type WaveNumber  = Quantity DWaveNumber
+
+type DMassDensity = 'Dim 'Neg3 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+type DDensity     = DMassDensity
+type MassDensity  = Quantity DMassDensity
+type Density      = MassDensity -- Short name.
+
+type DSpecificVolume = 'Dim 'Pos3 'Neg1 'Zero 'Zero 'Zero 'Zero 'Zero
+type SpecificVolume  = Quantity DSpecificVolume
+
+type DCurrentDensity = 'Dim 'Neg2 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+type CurrentDensity  = Quantity DCurrentDensity
+
+type DMagneticFieldStrength = 'Dim 'Neg1 'Zero 'Zero 'Pos1 'Zero 'Zero 'Zero
+type MagneticFieldStrength  = Quantity DMagneticFieldStrength
+
+type DAmountOfSubstanceConcentration = 'Dim 'Neg3 'Zero 'Zero 'Zero 'Zero 'Pos1 'Zero
+type DConcentration                  = DAmountOfSubstanceConcentration
+type AmountOfSubstanceConcentration  = Quantity DAmountOfSubstanceConcentration
+type Concentration                   = AmountOfSubstanceConcentration -- Short name.
+
+type DLuminance = 'Dim 'Neg2 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+type Luminance  = Quantity DLuminance
+
+
+{- $table3
+== Table 3
+
+SI coherent derived units with special names and symbols.
+
+-}
+
+type DPlaneAngle = DOne
+type PlaneAngle  = Dimensionless
+
+type DSolidAngle = DOne
+type SolidAngle  = Dimensionless
+
+type DFrequency = 'Dim 'Zero 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+type Frequency  = Quantity DFrequency
+
+type DForce = 'Dim 'Pos1 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+type Force  = Quantity DForce
+
+type DPressure = 'Dim 'Neg1 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+type DStress   = DPressure
+type Pressure  = Quantity DPressure
+type Stress    = Quantity DStress
+
+type DEnergy         = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+type DWork           = DEnergy
+type DQuantityOfHeat = DEnergy
+type Energy          = Quantity DEnergy
+type Work            = Quantity DWork
+type QuantityOfHeat  = Quantity DQuantityOfHeat
+
+type DPower       = 'Dim 'Pos2 'Pos1 'Neg3 'Zero 'Zero 'Zero 'Zero
+type DRadiantFlux = DPower
+type Power        = Quantity DPower
+type RadiantFlux  = Quantity DRadiantFlux
+
+type DElectricCharge        = 'Dim 'Zero 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
+type DQuantityOfElectricity = DElectricCharge
+type ElectricCharge         = Quantity DElectricCharge
+type QuantityOfElectricity  = Quantity DQuantityOfElectricity
+
+type DElectricPotential   = 'Dim 'Pos2 'Pos1 'Neg3 'Neg1 'Zero 'Zero 'Zero
+type DPotentialDifference = DElectricPotential
+type DElectromotiveForce  = DElectricPotential
+type ElectricPotential    = Quantity DElectricPotential
+type PotentialDifference  = Quantity DPotentialDifference
+type ElectromotiveForce   = Quantity DElectromotiveForce
+
+type DCapacitance = 'Dim 'Neg2 'Neg1 'Pos4 'Pos2 'Zero 'Zero 'Zero
+type Capacitance  = Quantity DCapacitance
+
+type DElectricResistance = 'Dim 'Pos2 'Pos1 'Neg3 'Neg2 'Zero 'Zero 'Zero
+type ElectricResistance  = Quantity DElectricResistance
+
+type DElectricConductance = 'Dim 'Neg2 'Neg1 'Pos3 'Pos2 'Zero 'Zero 'Zero
+type ElectricConductance  = Quantity DElectricConductance
+
+type DMagneticFlux = 'Dim 'Pos2 'Pos1 'Neg2 'Neg1 'Zero 'Zero 'Zero
+type MagneticFlux  = Quantity DMagneticFlux
+
+type DMagneticFluxDensity = 'Dim 'Zero 'Pos1 'Neg2 'Neg1 'Zero 'Zero 'Zero
+type MagneticFluxDensity  = Quantity DMagneticFluxDensity
+
+type DInductance = 'Dim 'Pos2 'Pos1 'Neg2 'Neg2 'Zero 'Zero 'Zero
+type Inductance  = Quantity DInductance
+
+type DLuminousFlux = DLuminousIntensity
+type LuminousFlux  = Quantity DLuminousFlux
+
+type DIlluminance = 'Dim 'Neg2 'Zero 'Zero 'Zero 'Zero 'Zero 'Pos1
+type Illuminance  = Quantity DIlluminance
+
+type DCelsiusTemperature = DThermodynamicTemperature
+type CelsiusTemperature  = Quantity DCelsiusTemperature
+
+type DActivity = DFrequency -- Activity of a radionuclide.
+type Activity  = Quantity DActivity
+
+type DAbsorbedDose   = 'Dim 'Pos2 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+type DSpecificEnergy = DAbsorbedDose
+type DKerma          = DAbsorbedDose
+type AbsorbedDose    = Quantity DAbsorbedDose
+type SpecificEnergy  = Quantity DSpecificEnergy -- Specific energy imparted.
+type Kerma           = Quantity DKerma
+
+type DDoseEquivalent            = DAbsorbedDose
+type DAmbientDoseEquivalent     = DDoseEquivalent
+type DDirectionalDoseEquivalent = DDoseEquivalent
+type DPersonalDoseEquivalent    = DDoseEquivalent
+type DEquivalentDose            = DDoseEquivalent
+type DoseEquivalent             = Quantity DDoseEquivalent
+type AmbientDoseEquivalent      = DoseEquivalent
+type DirectionalDoseEquivalent  = DoseEquivalent
+type PersonalDoseEquivalent     = DoseEquivalent
+type EquivalentDose             = DoseEquivalent
+
+type DCatalyticActivity = 'Dim 'Zero 'Zero 'Neg1 'Zero 'Zero 'Pos1 'Zero
+type CatalyticActivity  = Quantity DCatalyticActivity
+
+{- $table4
+== Table 4
+
+"Examples of SI coherent derived units expressed with the aid of SI derived
+units having special names and symbols."
+
+We use the same grouping as for table 2.
+
+-}
+
+type DAngularVelocity = DFrequency
+type AngularVelocity  = Quantity DAngularVelocity
+
+type DAngularAcceleration = 'Dim 'Zero 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+type AngularAcceleration  = Quantity DAngularAcceleration
+
+type DDynamicViscosity = 'Dim 'Neg1 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+type DynamicViscosity  = Quantity DDynamicViscosity
+
+type DMomentOfForce = DEnergy
+type MomentOfForce  = Quantity DMomentOfForce
+
+type DSurfaceTension = 'Dim 'Zero 'Pos1 'Neg2 'Zero 'Zero 'Zero 'Zero
+type SurfaceTension  = Quantity DSurfaceTension
+
+type DHeatFluxDensity = 'Dim 'Zero 'Pos1 'Neg3 'Zero 'Zero 'Zero 'Zero
+type DIrradiance      = DHeatFluxDensity
+type HeatFluxDensity  = Quantity DHeatFluxDensity
+type Irradiance       = Quantity DIrradiance
+
+type DRadiantIntensity = DPower
+type RadiantIntensity  = Quantity DRadiantIntensity
+
+type DRadiance = DIrradiance
+type Radiance  = Quantity DRadiance
+
+type DHeatCapacity = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Neg1 'Zero 'Zero
+type DEntropy      = DHeatCapacity
+type HeatCapacity  = Quantity DHeatCapacity
+type Entropy       = Quantity DEntropy
+
+type DSpecificHeatCapacity = 'Dim 'Pos2 'Zero 'Neg2 'Zero 'Neg1 'Zero 'Zero
+type DSpecificEntropy      = DSpecificHeatCapacity
+type SpecificHeatCapacity  = Quantity DSpecificHeatCapacity
+type SpecificEntropy       = Quantity DSpecificEntropy
+
+{-
+
+Specific energy was already defined in table 3.
+
+-}
+
+type DThermalConductivity = 'Dim 'Pos1 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
+type ThermalConductivity  = Quantity DThermalConductivity
+
+type DEnergyDensity = DPressure
+type EnergyDensity  = Quantity DEnergyDensity
+
+type DElectricFieldStrength = 'Dim 'Pos1 'Pos1 'Neg3 'Neg1 'Zero 'Zero 'Zero
+type ElectricFieldStrength  = Quantity DElectricFieldStrength
+
+type DElectricChargeDensity = 'Dim 'Neg3 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
+type ElectricChargeDensity  = Quantity DElectricChargeDensity
+
+type DElectricFluxDensity = 'Dim 'Neg2 'Zero 'Pos1 'Pos1 'Zero 'Zero 'Zero
+type ElectricFluxDensity  = Quantity DElectricFluxDensity
+
+type DPermittivity = 'Dim 'Neg3 'Neg1 'Pos4 'Pos2 'Zero 'Zero 'Zero
+type Permittivity  = Quantity DPermittivity
+
+type DPermeability = 'Dim 'Pos1 'Pos1 'Neg2 'Neg2 'Zero 'Zero 'Zero
+type Permeability  = Quantity DPermeability
+
+type DMolarEnergy = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Zero 'Neg1 'Zero
+type MolarEnergy  = Quantity DMolarEnergy
+
+type DMolarEntropy      = 'Dim 'Pos2 'Pos1 'Neg2 'Zero 'Neg1 'Neg1 'Zero
+type DMolarHeatCapacity = DMolarEntropy
+type MolarEntropy       = Quantity DMolarEntropy
+type MolarHeatCapacity  = Quantity DMolarHeatCapacity
+
+type DExposure = 'Dim 'Zero 'Neg1 'Pos1 'Pos1 'Zero 'Zero 'Zero
+type Exposure  = Quantity DExposure -- Exposure to x and gamma rays.
+
+type DAbsorbedDoseRate = 'Dim 'Pos2 'Zero 'Neg3 'Zero 'Zero 'Zero 'Zero
+type AbsorbedDoseRate  = Quantity DAbsorbedDoseRate
+
+{- $not-nist-guide
+Here we define additional quantities on an as-needed basis. We also
+provide some synonyms that we anticipate will be useful.
+-}
+
+type DImpulse = 'Dim 'Pos1 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+type Impulse  = Quantity DImpulse
+
+type DMomentum = DImpulse
+type Momentum = Quantity DMomentum
+
+type DMassFlow = 'Dim 'Zero 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+type MassFlow  = Quantity DMassFlow
+
+type DVolumeFlow = 'Dim 'Pos3 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+type VolumeFlow = Quantity DVolumeFlow
+
+type DGravitationalParameter = 'Dim 'Pos3 'Zero 'Neg2 'Zero 'Zero 'Zero 'Zero
+type GravitationalParameter  = Quantity DGravitationalParameter
+
+type DKinematicViscosity = 'Dim 'Pos2 'Zero 'Neg1 'Zero 'Zero 'Zero 'Zero
+type KinematicViscosity  = Quantity DKinematicViscosity
+
+type DFirstMassMoment = 'Dim 'Pos1 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+type FirstMassMoment = Quantity DFirstMassMoment
+
+type DMomentOfInertia = 'Dim 'Pos2 'Pos1 'Zero 'Zero 'Zero 'Zero 'Zero
+type MomentOfInertia = Quantity DMomentOfInertia
+
+type DAngularMomentum = 'Dim 'Pos2 'Pos1 'Neg1 'Zero 'Zero 'Zero 'Zero
+type AngularMomentum = Quantity DAngularMomentum
+
+{-
+
+The reciprocal of thermal conductivity.
+
+-}
+
+type DThermalResistivity = 'Dim 'Neg1 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
+type ThermalResistivity = Quantity DThermalResistivity
+
+{-
+
+Thermal conductance and resistance quantities after http://en.wikipedia.org/wiki/Thermal_conductivity#Definitions.
+
+-}
+
+type DThermalConductance = 'Dim 'Pos2 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
+type ThermalConductance = Quantity DThermalConductance
+
+type DThermalResistance = 'Dim 'Neg2 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
+type ThermalResistance = Quantity DThermalResistance
+
+type DHeatTransferCoefficient = 'Dim 'Zero 'Pos1 'Neg3 'Zero 'Neg1 'Zero 'Zero
+type HeatTransferCoefficient = Quantity DHeatTransferCoefficient
+
+type DThermalAdmittance = DHeatTransferCoefficient
+type ThermalAdmittance = HeatTransferCoefficient
+
+type DThermalInsulance = 'Dim 'Zero 'Neg1 'Pos3 'Zero 'Pos1 'Zero 'Zero
+type ThermalInsulance = Quantity DThermalInsulance
+
+type DJerk = 'Dim 'Pos1 'Zero 'Neg3 'Zero 'Zero 'Zero 'Zero
+type Jerk = Quantity DJerk
+
+type Angle = PlaneAngle -- Abbreviation
+type DAngle = DPlaneAngle -- Abbreviation
+
+type Thrust = Force
+type DThrust = DForce
+
+type Torque = MomentOfForce
+type DTorque = DMomentOfForce
+
+type EnergyPerUnitMass = SpecificEnergy
+type DEnergyPerUnitMass = DSpecificEnergy
+
+{- $powers-of-length-units
+It is permissible to express powers of length units by prefixing
+'square' and 'cubic' (see section 9.6 "Spelling unit names raised
+to powers" of <#note1 [1]>).
+
+These definitions may seem slightly out of place but these is no
+obvious place where they should be. Here they are at least close
+to the definitions of 'DLength' and 'DVolume'.
+-}
+
+-- | Constructs a unit of area from a unit of length, taking the area of a square whose sides are that length.
+square :: (Fractional a, Typeable m) => Unit m DLength a -> Unit 'NonMetric DArea a
+square x = x ^ pos2
+
+-- | Constructs a unit of volume from a unit of length, taking the volume of a cube whose sides are that length.
+cubic  :: (Fractional a, Typeable m) => Unit m DLength a -> Unit 'NonMetric DVolume a
+cubic  x = x ^ pos3
diff --git a/src/Numeric/Units/Dimensional/SIUnits.hs b/src/Numeric/Units/Dimensional/SIUnits.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/SIUnits.hs
@@ -0,0 +1,297 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE NumDecimals #-}
+{-# LANGUAGE RankNTypes #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+= Summary
+
+This module defines the SI prefixes, the SI base units and the SI
+derived units. It also defines the units outside of the SI that are
+accepted for use with the SI. Any chapters, sections or tables
+referenced are from <#note1 [1]> unless otherwise specified.
+
+= References
+
+1. #note1# http://physics.nist.gov/Pubs/SP811/
+2. #note2# http://en.wikipedia.org/wiki/Minute_of_arc
+3. #note3# http://en.wikipedia.org/wiki/Astronomical_unit
+
+-}
+
+module Numeric.Units.Dimensional.SIUnits 
+(
+  -- * SI Base Units
+  -- $base-units
+  metre, meter, gram, second, ampere, kelvin, mole, candela,
+  -- * SI Derived Units
+  -- $derived-units
+  radian, steradian, hertz, newton, pascal, joule, watt, coulomb, volt, farad, ohm, siemens, weber, tesla, henry, lumen, lux,
+  -- ** Celsius Temperature
+  -- $celsius
+  degreeCelsius, fromDegreeCelsiusAbsolute, toDegreeCelsiusAbsolute,
+  -- ** Units Admitted for Reasons of Safeguarding Human Health
+  -- $health
+  becquerel, gray, sievert, katal,
+  -- * Units Accepted for Use with the SI
+  -- $accepted-units
+  minute, hour, day, 
+  hectare, litre, liter, tonne, metricTon,
+  -- ** Units of Plane Angle
+  -- $arc-units
+  degree, arcminute, arcsecond,
+  -- $arc-units-alternate
+  degreeOfArc, minuteOfArc, secondOfArc,
+  -- ** Units Formerly Defined By Experiment
+  -- $values-obtained-experimentally
+  astronomicalUnit,
+  -- * SI Prefixes
+  -- $multiples
+  deka, deca, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta,
+  -- $submultiples
+  deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto
+)
+where
+
+import Numeric.Units.Dimensional
+import Numeric.Units.Dimensional.Quantities
+import Numeric.Units.Dimensional.UnitNames (PrefixName, applyPrefix, nMeter, nGram, nSecond, nAmpere, nKelvin, nMole, nCandela)
+import qualified Numeric.Units.Dimensional.UnitNames as N
+import Numeric.Units.Dimensional.UnitNames.Internal (ucum, ucumMetric)
+import Numeric.NumType.DK.Integers ( pos3 )
+import Prelude ( ($), Num, Fractional, Floating, Integer, Rational, recip)
+import qualified Prelude
+
+{- $multiples
+Prefixes are used to form decimal multiples and submultiples of SI
+Units as described in section 4.4. We will define the SI prefixes
+in terms of the 'prefix' function which applies a scale factor to a
+unit.
+
+By defining SI prefixes as functions applied to a 'Unit' we satisfy
+section 6.2.6 "Unacceptability of stand-alone prefixes".
+
+We define all SI prefixes from Table 5. Multiples first.
+-}
+
+applyMultiple :: (Num a) => PrefixName -> Integer -> Unit 'Metric d a -> Unit 'NonMetric d a
+applyMultiple p x u = mkUnitZ (applyPrefix p (name u)) x u
+
+deka, deca, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta
+  :: Num a => Unit 'Metric d a -> Unit 'NonMetric d a
+deka  = applyMultiple N.deka 10 -- International English.
+deca  = deka      -- American English.
+hecto = applyMultiple N.hecto 100
+kilo  = applyMultiple N.kilo 1e3
+mega  = applyMultiple N.mega 1e6
+giga  = applyMultiple N.giga 1e9
+tera  = applyMultiple N.tera 1e12
+peta  = applyMultiple N.peta 1e15
+exa   = applyMultiple N.exa 1e18
+zetta = applyMultiple N.zetta 1e21
+yotta = applyMultiple N.yotta 1e24
+
+{- $submultiples
+Then the submultiples.
+-}
+
+applySubmultiple :: (Fractional a) => PrefixName -> Rational -> Unit 'Metric d a -> Unit 'NonMetric d a
+applySubmultiple p x u = mkUnitQ (applyPrefix p (name u)) x u
+
+deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto
+  :: Fractional a => Unit 'Metric d a -> Unit 'NonMetric d a
+deci  = applySubmultiple N.deci 0.1
+centi = applySubmultiple N.centi 0.01
+milli = applySubmultiple N.milli 1e-3
+micro = applySubmultiple N.micro 1e-6
+nano  = applySubmultiple N.nano 1e-9
+pico  = applySubmultiple N.pico 1e-12
+femto = applySubmultiple N.femto 1e-15
+atto  = applySubmultiple N.atto 1e-18
+zepto = applySubmultiple N.zepto 1e-21
+yocto = applySubmultiple N.yocto 1e-24
+
+{- $base-units
+These are the base units from section 4.1. To avoid a
+myriad of one-letter functions that would doubtlessly cause clashes
+and frustration in users' code we spell out all unit names in full,
+as we did for prefixes. We also elect to spell the unit names in
+singular form, as allowed by section 9.7 "Other spelling conventions".
+
+We define the SI base units in the order of table 1.
+-}
+
+metre, meter :: Num a => Unit 'Metric DLength a
+metre = mkUnitZ nMeter 1 siUnit -- International English.
+meter = metre         -- American English.
+
+{-
+
+For mass the SI base unit is kilogram. For sensible prefixes we
+define gram here (see section 6.2.7 "Prefixes and the kilogram").
+The drawback is that we are forced to use 'Fractional'.
+
+-}
+
+gram    :: Fractional a => Unit 'Metric DMass a
+gram    = mkUnitQ nGram 1e-3 siUnit
+second  :: Num a => Unit 'Metric DTime a
+second  = mkUnitZ nSecond 1 siUnit
+ampere  :: Num a => Unit 'Metric DElectricCurrent a
+ampere  = mkUnitZ nAmpere 1 siUnit
+kelvin  :: Num a => Unit 'Metric DThermodynamicTemperature a
+kelvin  = mkUnitZ nKelvin 1 siUnit
+mole    :: Num a => Unit 'Metric DAmountOfSubstance a
+mole    = mkUnitZ nMole 1 siUnit
+candela :: Num a => Unit 'Metric DLuminousIntensity a
+candela = mkUnitZ nCandela 1 siUnit
+
+{- $derived-units
+From Table 3, SI derived units with special names and symbols, including the
+radian and steradian.
+-}
+
+radian :: Num a => Unit 'Metric DPlaneAngle a
+radian = mkUnitZ (ucumMetric "rad" "rad" "radian") 1 siUnit -- meter * meter ^ neg1
+steradian :: Num a => Unit 'Metric DSolidAngle a
+steradian = mkUnitZ (ucumMetric "sr" "sr" "steradian") 1 siUnit -- meter ^ pos2 * meter ^ neg2
+hertz :: Num a => Unit 'Metric DFrequency a
+hertz = mkUnitZ (ucumMetric "Hz" "Hz" "Hertz") 1 $ siUnit
+newton :: Num a => Unit 'Metric DForce a
+newton = mkUnitZ (ucumMetric "N" "N" "Newton") 1 $ siUnit
+pascal :: Num a => Unit 'Metric DPressure a
+pascal = mkUnitZ (ucumMetric "Pa" "Pa" "Pascal") 1 $ siUnit
+joule :: Num a => Unit 'Metric DEnergy a
+joule = mkUnitZ (ucumMetric "J" "J" "Joule") 1 $ siUnit
+watt :: Num a => Unit 'Metric DPower a
+watt = mkUnitZ (ucumMetric "W" "W" "Watt") 1 $ siUnit
+coulomb :: Num a => Unit 'Metric DElectricCharge a
+coulomb = mkUnitZ (ucumMetric "C" "C" "Coulomb") 1 $ siUnit
+volt :: Num a => Unit 'Metric DElectricPotential a
+volt = mkUnitZ (ucumMetric "V" "V" "Volt") 1 $ siUnit
+farad :: Num a => Unit 'Metric DCapacitance a
+farad = mkUnitZ (ucumMetric "F" "F" "Farad") 1 $ siUnit
+ohm :: Num a => Unit 'Metric DElectricResistance a
+ohm = mkUnitZ (ucumMetric "Ohm" "Ω" "Ohm") 1 $ siUnit
+siemens :: Num a => Unit 'Metric DElectricConductance a
+siemens = mkUnitZ (ucumMetric "S" "S" "Siemens") 1 $ siUnit
+weber :: Num a => Unit 'Metric DMagneticFlux a
+weber = mkUnitZ (ucumMetric "Wb" "Wb" "Weber") 1 $ siUnit
+tesla :: Num a => Unit 'Metric DMagneticFluxDensity a
+tesla = mkUnitZ (ucumMetric "T" "T" "Tesla") 1 $ siUnit
+henry :: Num a => Unit 'Metric DInductance a
+henry = mkUnitZ (ucumMetric "H" "H" "Henry") 1 $ siUnit
+
+{-
+We defer the definition of Celcius temperature to another section (would
+appear here if we stricly followed table 3).
+-}
+
+lumen :: Num a => Unit 'Metric DLuminousFlux a
+lumen = mkUnitZ (ucumMetric "lm" "lm" "lumen") 1 $ siUnit
+lux :: Num a => Unit 'Metric DIlluminance a
+lux = mkUnitZ (ucumMetric "lx" "lx" "lux") 1 $ siUnit
+
+{- $celsius
+A problematic area is units which increase proportionally to the
+base SI units but cross zero at a different point. An example would
+be degrees Celsius (see section 4.2.1.1). The author feels that it
+is appropriate to define a unit for use with relative quantities
+(taking only into account the proportionality) and complement the
+unit with functions for converting absolute values.
+
+The function 'fromDegreeCelsiusAbsolute' should be used in lieu of
+"*~ degreeCelsius" when working with absolute temperatures. Similarily,
+'toDegreeCelsiusAbsolute' should be used in lieu of "/~ degreeCelsius"
+when working with absolute temperatures.
+-}
+
+degreeCelsius :: Num a => Unit 'Metric DCelsiusTemperature a
+degreeCelsius = kelvin
+
+fromDegreeCelsiusAbsolute :: Floating a => a -> ThermodynamicTemperature a
+fromDegreeCelsiusAbsolute x = x *~ degreeCelsius + 273.15 *~ degreeCelsius
+toDegreeCelsiusAbsolute :: Floating a => ThermodynamicTemperature a -> a
+toDegreeCelsiusAbsolute x = (x - 273.15 *~ degreeCelsius) /~ degreeCelsius
+
+{- $health
+
+The last units from Table 3 are SI derived units with special names and symbols admitted for reasons
+of safeguarding human health.
+-}
+
+becquerel :: Num a => Unit 'Metric DActivity a
+becquerel = mkUnitZ (ucumMetric "Bq" "Bq" "Becquerel") 1 $ siUnit
+gray :: Num a => Unit 'Metric DAbsorbedDose a
+gray = mkUnitZ (ucumMetric "Gy" "Gy" "Gray") 1 $ siUnit
+sievert :: Num a => Unit 'Metric DDoseEquivalent a
+sievert = mkUnitZ (ucumMetric "Sv" "Sv" "Sievert") 1 $ siUnit
+katal :: Num a => Unit 'Metric DCatalyticActivity a
+katal = mkUnitZ (ucumMetric "kat" "kat" "katal") 1 $ siUnit
+
+{- $accepted-units
+There are several units that are not strictly part of the SI but
+are either permanently or temporarily accepted for use with the SI.
+We define the permanently accepted ones in this module.
+
+From Table 6, Units accepted for use with the SI.
+
+We start with time which we grant exclusive rights to 'minute' and
+'second'.
+-}
+minute, hour, day :: Num a => Unit 'NonMetric DTime a
+minute = mkUnitZ (ucum "min" "min" "minute") 60 $ second
+hour   = mkUnitZ (ucum "h" "h" "hour")       60 $ minute
+day    = mkUnitZ (ucum "d" "d" "day")        24 $ hour -- Mean solar day.
+
+{- $arc-units
+
+Since 'minute' and 'second' are already in use for time we use
+'arcminute' and 'arcsecond' <#note2 [2]> for plane angle instead.
+-}
+
+degree, arcminute, arcsecond :: Floating a => Unit 'NonMetric DPlaneAngle a
+degree    = mkUnitR (ucum "deg" "°" "degree")    (Prelude.pi Prelude./ 180) $ radian
+arcminute = mkUnitR (ucum "'" "'" "arcminute")   (recip 60)                 $ degreeOfArc
+arcsecond = mkUnitR (ucum "''" "''" "arcsecond") (recip 60)                 $ minuteOfArc
+
+{- $arc-units-alternate
+Alternate (longer) forms of the above. In particular 'degreeOfArc'
+can be used if there is a percieved need to disambiguate from e.g.
+temperature.
+-}
+
+degreeOfArc, minuteOfArc, secondOfArc :: Floating a => Unit 'NonMetric DPlaneAngle a
+degreeOfArc = degree
+secondOfArc = arcsecond
+minuteOfArc = arcminute
+
+hectare :: Fractional a => Unit 'NonMetric DArea a
+hectare = square (hecto meter)
+
+litre, liter :: Fractional a => Unit 'Metric DVolume a
+litre = mkUnitQ (ucumMetric "L" "L" "litre") 1 $ deci meter ^ pos3 -- International English.
+liter = litre             -- American English.
+
+tonne, metricTon :: Num a => Unit 'Metric DMass a
+tonne     = mkUnitZ (ucumMetric "t" "t" "tonne") 1000 $ siUnit -- Name in original SI text.
+metricTon = tonne                   -- American name.
+
+{- $values-obtained-experimentally
+We decline to provide here those units - listed in Table 7 - which,
+while accepted for use with the SI, have values which are determined experimentally.
+For versioning purposes, those units can be found in "Numeric.Units.Dimensional.NonSI".
+
+However, in 2012 the IAU redefined the astronomical unit as a conventional
+unit of length directly tied to the meter, with a length of exactly
+149,597,870,700 m and the official abbreviation of au <#note3 [3]>. We therefore include it here.
+-}
+
+astronomicalUnit :: Num a => Unit 'NonMetric DLength a
+astronomicalUnit = mkUnitZ (ucum "AU" "AU" "astronomical unit") 149597870700 $ meter
diff --git a/src/Numeric/Units/Dimensional/UnitNames.hs b/src/Numeric/Units/Dimensional/UnitNames.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/UnitNames.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE PatternSynonyms #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+This module provides types and functions for manipulating unit names.
+
+Please note that the details of the name representation may be less stable than the other APIs
+provided by this package, as new features using them are still being developed.
+
+-}
+module Numeric.Units.Dimensional.UnitNames
+(
+  -- * Data Types
+  UnitName, NameAtom, PrefixName, Metricality(..),
+  -- * Construction of Unit Names
+  atom, applyPrefix, (*), (/), (^), product, reduce, grouped,
+  -- * Standard Names
+  baseUnitName,
+  -- ** Names for the Base Units
+  nOne, nMeter, nGram, nKilogram, nSecond, nAmpere, nKelvin, nMole, nCandela,
+  -- ** Names for the SI Metric Prefixes
+  deka, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta,
+  deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto,
+  -- * Convenience Type Synonyms for Unit Name Transformations
+  UnitNameTransformer, UnitNameTransformer2,
+  -- * Forgetting Unwanted Phantom Types
+  weaken, strengthen, relax
+)
+where
+
+import Numeric.Units.Dimensional.UnitNames.Internal
+import Numeric.Units.Dimensional.Variants
+import Prelude hiding ((*), (/), (^), product)
diff --git a/src/Numeric/Units/Dimensional/UnitNames/InterchangeNames.hs b/src/Numeric/Units/Dimensional/UnitNames/InterchangeNames.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/UnitNames/InterchangeNames.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+
+module Numeric.Units.Dimensional.UnitNames.InterchangeNames
+(
+  InterchangeNameAuthority(..),
+  InterchangeName(..),
+  HasInterchangeName(..)
+)
+where
+
+import Data.Data
+import GHC.Generics
+
+-- | Represents the authority which issued an interchange name for a unit.
+data InterchangeNameAuthority = UCUM -- ^ The interchange name originated with the Unified Code for Units of Measure.
+                              | DimensionalLibrary -- ^ The interchange name originated with the dimensional library.
+                              | Custom -- ^ The interchange name originated with a user of the dimensional library.
+  deriving (Eq, Ord, Show, Data, Typeable, Generic)
+
+data InterchangeName = InterchangeName { name :: String, authority :: InterchangeNameAuthority }
+  deriving (Eq, Ord, Data, Typeable, Generic)
+
+instance Show InterchangeName where
+  show n = name n ++ " (Issued by " ++ show (authority n) ++ ")"
+
+-- | Determines the authority which issued the interchange name of a unit or unit name.
+-- For composite units, this is the least-authoritative interchange name of any constituent name.
+--
+-- Note that the least-authoritative authority is the one sorted as greatest by the 'Ord' instance of 'InterchangeNameAuthority'.
+class HasInterchangeName a where
+  interchangeName :: a -> InterchangeName
+
+instance HasInterchangeName InterchangeName where
+  interchangeName = id
diff --git a/src/Numeric/Units/Dimensional/UnitNames/Internal.hs b/src/Numeric/Units/Dimensional/UnitNames/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/UnitNames/Internal.hs
@@ -0,0 +1,304 @@
+{-# OPTIONS_HADDOCK not-home #-}
+
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving #-}
+
+module Numeric.Units.Dimensional.UnitNames.Internal
+where
+
+import Control.Monad (join)
+import Data.Data
+#if MIN_VERSION_base(4, 8, 0)
+import Data.Foldable (toList)
+#else
+import Data.Foldable (Foldable, toList)
+#endif
+import GHC.Generics
+import Numeric.Units.Dimensional.Dimensions.TermLevel (Dimension', asList, HasDimension(..))
+import Numeric.Units.Dimensional.UnitNames.InterchangeNames
+import Numeric.Units.Dimensional.Variants (Metricality(..))
+import Prelude hiding ((*), (/), (^), product)
+import qualified Prelude as P
+
+-- | The name of a unit.
+data UnitName (m :: Metricality) where
+  -- The name of the unit of dimensionless values.
+  One :: UnitName 'NonMetric
+  -- A name of an atomic unit to which metric prefixes may be applied.
+  MetricAtomic :: NameAtom ('UnitAtom 'Metric) -> UnitName 'Metric
+  -- A name of an atomic unit to which metric prefixes may not be applied.
+  Atomic :: NameAtom ('UnitAtom 'NonMetric) -> UnitName 'NonMetric
+  -- A name of a prefixed unit.
+  Prefixed :: PrefixName -> UnitName 'Metric -> UnitName 'NonMetric
+  -- A compound name formed from the product of two names.
+  Product :: UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric
+  -- A compound name formed from the quotient of two names.
+  Quotient :: UnitName 'NonMetric -> UnitName 'NonMetric -> UnitName 'NonMetric
+  -- A compound name formed by raising a unit name to an integer power.
+  Power :: UnitName 'NonMetric -> Int -> UnitName 'NonMetric
+  -- A compound name formed by grouping another name, which is generally compound.
+  Grouped :: UnitName 'NonMetric -> UnitName 'NonMetric
+  -- A weakened name formed by forgetting whether it could accept a metric prefix.
+  -- Differs from 'Grouped' because it is displayed without parentheses.
+  Weaken :: UnitName 'Metric -> UnitName 'NonMetric
+  deriving (Typeable)
+
+deriving instance Eq (UnitName m)
+
+instance Show (UnitName m) where
+  show One = "1"
+  show (MetricAtomic a) = abbreviation_en a
+  show (Atomic a) = abbreviation_en a
+  show (Prefixed a n) = abbreviation_en a ++ show n
+  show (Product n1 n2) = show n1 ++ " " ++ show n2
+  show (Quotient n1 n2) = show n1 ++ " / " ++ show n2
+  show (Power x n) = show x ++ "^" ++ show n
+  show (Grouped n) = "(" ++ show n ++ ")"
+  show (Weaken n) = show n
+
+isAtomic :: UnitName m -> Bool
+isAtomic (One) = True
+isAtomic (MetricAtomic _) = True
+isAtomic (Atomic _) = True
+isAtomic (Prefixed _ _) = True
+isAtomic (Grouped _) = True
+isAtomic (Weaken n) = isAtomic n
+isAtomic _ = False
+
+isAtomicOrProduct :: UnitName m -> Bool
+isAtomicOrProduct (Product _ _) = True
+isAtomicOrProduct n = isAtomic n
+
+-- reduce by algebraic simplifications
+reduce :: UnitName m -> UnitName m
+reduce (One) = One
+reduce n@(MetricAtomic _) = n
+reduce n@(Atomic _) = n
+reduce n@(Prefixed _ _) = n
+reduce (Product n1 n2) = reduce' (reduce n1 * reduce n2)
+reduce (Quotient n1 n2) = reduce' (reduce n1 * reduce n2)
+reduce (Power n x) = reduce' ((reduce n) ^ x)
+reduce (Grouped n) = reduce' (Grouped (reduce n))
+reduce (Weaken n) = reduce' (Weaken (reduce n))
+
+-- reduce, knowing that subterms are already in reduced form
+reduce' :: UnitName m -> UnitName m
+reduce' (Product One n) = reduce' n
+reduce' (Product n One) = reduce' n
+reduce' (Power (Power n x1) x2) = reduce (n ^ (x1 P.* x2))
+reduce' (Power (Grouped (Power n x1)) x2) = reduce (n ^ (x1 P.* x2))
+reduce' (Power _ 0) = One
+reduce' (Power n 1) = reduce' n
+reduce' (Grouped n) = reduce' n
+reduce' n@(Weaken (MetricAtomic _)) = n
+reduce' n = n
+
+data NameAtomType = UnitAtom Metricality
+                  | PrefixAtom
+  deriving (Eq, Ord, Data, Typeable, Generic)
+
+-- | The name of a metric prefix.
+type PrefixName = NameAtom 'PrefixAtom
+
+nOne :: UnitName 'NonMetric
+nOne = One
+
+nMeter :: UnitName 'Metric
+nMeter = ucumMetric "m" "m" "metre"
+
+nGram :: UnitName 'Metric
+nGram = ucumMetric "g" "g" "gram"
+
+nKilogram :: UnitName 'NonMetric
+nKilogram = applyPrefix kilo nGram
+
+nSecond :: UnitName 'Metric
+nSecond = ucumMetric "s" "s" "second"
+
+nAmpere :: UnitName 'Metric
+nAmpere = ucumMetric "A" "A" "Ampere"
+
+nKelvin :: UnitName 'Metric
+nKelvin = ucumMetric "K" "K" "Kelvin"
+
+nMole :: UnitName 'Metric
+nMole = ucumMetric "mol" "mol" "mole"
+
+nCandela :: UnitName 'Metric
+nCandela = ucumMetric "cd" "cd" "candela"
+
+-- | The name of the base unit associated with a specified dimension.
+baseUnitName :: Dimension' -> UnitName 'NonMetric
+baseUnitName d = let powers = asList $ dimension d
+                  in reduce . product $ zipWith (^) baseUnitNames powers
+
+baseUnitNames :: [UnitName 'NonMetric]
+baseUnitNames = [weaken nMeter, nKilogram, weaken nSecond, weaken nAmpere, weaken nKelvin, weaken nMole, weaken nCandela]
+
+deka, hecto, kilo, mega, giga, tera, peta, exa, zetta, yotta :: PrefixName
+deka  = prefix "da" "da" "deka"
+hecto = prefix "h" "h" "hecto"
+kilo  = prefix "k" "k" "kilo"
+mega  = prefix "M" "M" "mega"
+giga  = prefix "G" "G" "giga"
+tera  = prefix "T" "T" "tera"
+peta  = prefix "P" "P" "peta"
+exa   = prefix "E" "E" "exa"
+zetta = prefix "Z" "Z" "zetta"
+yotta = prefix "Y" "Y" "yotta"
+deci, centi, milli, micro, nano, pico, femto, atto, zepto, yocto :: PrefixName
+deci  = prefix "d" "d" "deci"
+centi = prefix "c" "c" "centi"
+milli = prefix "m" "m" "milli"
+micro = prefix "u" "μ" "micro"
+nano  = prefix "n" "n" "nano"
+pico  = prefix "p" "p" "pico"
+femto = prefix "f" "f" "femto"
+atto  = prefix "a" "a" "atto"
+zepto = prefix "z" "z" "zepto"
+yocto = prefix "y" "y" "yocto"
+
+-- | Forms a 'UnitName' from a 'Metric' name by applying a metric prefix.
+applyPrefix :: PrefixName -> UnitName 'Metric -> UnitName 'NonMetric
+applyPrefix = Prefixed
+
+{-
+We will reuse the operators and function names from the Prelude.
+To prevent unpleasant surprises we give operators the same fixity
+as the Prelude.
+-}
+
+infixr 8  ^
+infixl 7  *, /
+
+-- | Form a 'UnitName' by taking the product of two others.
+(*) :: UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
+a * b = Product (weaken a) (weaken b)
+
+-- | Form a 'UnitName' by dividing one by another.
+(/) :: UnitName m1 -> UnitName m2 -> UnitName 'NonMetric
+n1 / n2 | isAtomicOrProduct n1 = Quotient (weaken n1) (weaken n2)
+        | otherwise            = Quotient (grouped n1) (weaken n2)
+
+-- | Form a 'UnitName' by raising a name to an integer power.
+(^) :: UnitName m -> Int -> UnitName 'NonMetric
+x ^ n | isAtomic x = Power (weaken x) n
+      | otherwise  = Power (grouped x) n
+
+-- | Convert a 'UnitName' which may or may not be 'Metric' to one
+-- which is certainly 'NonMetric'.
+weaken :: UnitName m -> UnitName 'NonMetric
+weaken n@(MetricAtomic _) = Weaken n -- we really only need this one case and a catchall, but the typechecker can't see it
+weaken n@One = n
+weaken n@(Atomic _) = n
+weaken n@(Prefixed _ _) = n
+weaken n@(Product _ _) = n
+weaken n@(Quotient _ _) = n
+weaken n@(Power _ _) = n
+weaken n@(Grouped _) = n
+weaken n@(Weaken _) = n
+
+-- | Attempt to convert a 'UnitName' which may or may not be 'Metric' to one
+-- which is certainly 'Metric'.
+strengthen :: UnitName m -> Maybe (UnitName 'Metric)
+strengthen n@(MetricAtomic _) = Just n
+strengthen (Weaken n) = strengthen n
+strengthen _ = Nothing
+
+-- | Convert a 'UnitName' of one 'Metricality' into a name of the other metricality by
+-- strengthening or weakening if neccessary. Because it may not be possible to strengthen,
+-- the result is returned in a 'Maybe' wrapper.
+relax :: forall m1 m2.(Typeable m1, Typeable m2) => UnitName m1 -> Maybe (UnitName m2)
+relax n = go (typeRep (Proxy :: Proxy m1)) (typeRep (Proxy :: Proxy m2)) n
+  where
+    metric = typeRep (Proxy :: Proxy 'Metric)
+    nonMetric = typeRep (Proxy :: Proxy 'NonMetric)
+    go :: TypeRep -> TypeRep -> UnitName m1 -> Maybe (UnitName m2)
+    go p1 p2 | p1 == p2 = cast
+             | (p1 == nonMetric) && (p2 == metric) = join . fmap gcast . strengthen
+             | (p1 == metric) && (p2 == nonMetric) = cast . weaken
+             | otherwise = error "Should be unreachable. TypeRep of an unexpected Metricality encountered."
+
+-- | Constructs a 'UnitName' by applying a grouping operation to
+-- another 'UnitName', which may be useful to express precedence.
+grouped :: UnitName m -> UnitName 'NonMetric
+grouped = Grouped . weaken
+
+-- | Represents the name of an atomic unit or prefix.
+data NameAtom (m :: NameAtomType)
+  = NameAtom 
+  {
+    _interchangeName :: InterchangeName, -- ^ The interchange name of the unit.
+    abbreviation_en :: String, -- ^ The abbreviated name of the unit in international English
+    name_en :: String -- ^ The full name of the unit in international English
+  }
+  deriving (Eq, Ord, Data, Typeable, Generic)
+
+instance HasInterchangeName (NameAtom m) where
+  interchangeName = _interchangeName
+
+instance HasInterchangeName (UnitName m) where
+  interchangeName One = InterchangeName { name = "1", authority = UCUM }
+  interchangeName (MetricAtomic a) = interchangeName a
+  interchangeName (Atomic a) = interchangeName a
+  interchangeName (Prefixed p n) = let n' = (name . interchangeName $ p) ++ (name . interchangeName $ n)
+                                       a' = max (authority . interchangeName $ p) (authority . interchangeName $ n)
+                                    in InterchangeName { name = n', authority = a' }
+  interchangeName (Product n1 n2) = let n' = (name . interchangeName $ n1) ++ "." ++ (name . interchangeName $ n2)
+                                        a' = max (authority . interchangeName $ n1) (authority . interchangeName $ n2)
+                                     in InterchangeName { name = n', authority = a' }
+  interchangeName (Quotient n1 n2) = let n' = (name . interchangeName $ n1) ++ "/" ++ (name . interchangeName $ n2)
+                                         a' = max (authority . interchangeName $ n1) (authority . interchangeName $ n2)
+                                      in InterchangeName { name = n', authority = a' }
+  interchangeName (Power n x) = let n' = (name . interchangeName $ n) ++ (show x)
+                                 in InterchangeName { name = n', authority = authority . interchangeName $ n }
+  interchangeName (Grouped n) = let n' = "(" ++ (name . interchangeName $ n) ++ ")"
+                                 in InterchangeName { name = n', authority = authority . interchangeName $ n }
+  interchangeName (Weaken n) = interchangeName n
+
+prefix :: String -> String -> String -> PrefixName
+prefix i a f = NameAtom (InterchangeName i UCUM) a f
+
+ucumMetric :: String -> String -> String -> UnitName 'Metric
+ucumMetric i a f = MetricAtomic $ NameAtom (InterchangeName i UCUM) a f
+
+ucum :: String -> String -> String -> UnitName 'NonMetric
+ucum i a f = Atomic $ NameAtom (InterchangeName i UCUM) a f
+
+dimensionalAtom :: String -> String -> String -> UnitName 'NonMetric
+dimensionalAtom i a f = Atomic $ NameAtom (InterchangeName i DimensionalLibrary) a f
+
+-- | Constructs an atomic name for a custom unit.
+atom :: String -- ^ Interchange name
+     -> String -- ^ Abbreviated name in international English
+     -> String -- ^ Full name in international English
+     -> UnitName 'NonMetric
+atom i a f = Atomic $ NameAtom (InterchangeName i Custom) a f
+
+-- | The type of a unit name transformation that may be associated with an operation that takes a single unit as input.
+type UnitNameTransformer = (forall m.UnitName m -> UnitName 'NonMetric)
+
+-- | The type of a unit name transformation that may be associated with an operation that takes two units as input.
+type UnitNameTransformer2 = (forall m1 m2.UnitName m1 -> UnitName m2 -> UnitName 'NonMetric)
+
+-- | Forms the product of a list of 'UnitName's.
+--
+-- If you wish to form a heterogenous product of 'Metric' and 'NonMetric' units
+-- you should apply 'weaken' to the 'Metric' ones.
+product :: Foldable f => f (UnitName 'NonMetric) -> UnitName 'NonMetric
+product = go . toList
+  where
+    -- This is not defined using a simple fold so that it does not complicate the product with
+    -- valid but meaningless occurences of nOne.
+    go :: [UnitName 'NonMetric] -> UnitName 'NonMetric
+    go [] = nOne
+    go [n] = n
+    go (n : ns) = n * go ns
diff --git a/src/Numeric/Units/Dimensional/Variants.hs b/src/Numeric/Units/Dimensional/Variants.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Units/Dimensional/Variants.hs
@@ -0,0 +1,71 @@
+{-# OPTIONS_HADDOCK not-home, show-extensions #-}
+
+{-# LANGUAGE AutoDeriveTypeable #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+
+{- |
+   Copyright  : Copyright (C) 2006-2015 Bjorn Buckwalter
+   License    : BSD3
+
+   Maintainer : bjorn@buckwalter.se
+   Stability  : Stable
+   Portability: GHC only
+
+Provides a type level representation of 'Variant's of dimensional values,
+which may be quantities or units.
+-}
+module Numeric.Units.Dimensional.Variants
+(
+  type Variant(..),
+  Metricality(..),
+  type (*), type Weaken
+)
+where
+
+import Data.Data
+import GHC.Generics
+
+-- | Encodes whether a unit is a metric unit, that is, whether it can be combined
+-- with a metric prefix to form a related unit.
+data Metricality = Metric    -- ^ Capable of receiving a metric prefix.
+                 | NonMetric -- ^ Incapable of receiving a metric prefix.
+  deriving (Eq, Ord, Data, Typeable, Generic)
+
+{-
+The variety 'v' of 'Dimensional'
+
+The phantom type variable v is used to distinguish between units
+and quantities. It must be one of the following:
+-}
+
+-- | The kind of variants of dimensional values.
+data Variant = DQuantity         -- ^ The value is a quantity.
+             | DUnit Metricality -- ^ The value is a unit, possibly a 'Metric' unit.
+  deriving (Eq, Ord, Data, Typeable, Generic)
+
+{-
+We will reuse the operators and function names from the Prelude.
+To prevent unpleasant surprises we give operators the same fixity
+as the Prelude.
+-}
+
+infixl 7  *
+
+-- | Forms the product of two 'Variant's.
+--
+-- The product of units is a non-metric unit.
+--
+-- The product of quantities is a quantity.
+type family (v1 :: Variant) * (v2 :: Variant) :: Variant where
+  'DUnit m1  * 'DUnit m2  = 'DUnit 'NonMetric
+  'DQuantity * 'DQuantity = 'DQuantity 
+
+-- | Weakens a 'Variant' by forgetting possibly uninteresting type-level information.
+type family Weaken (v :: Variant) :: Variant where
+  Weaken 'DQuantity = 'DQuantity
+  Weaken ('DUnit m) = 'DUnit 'NonMetric
diff --git a/tests/Numeric/Units/Dimensional/QuantitiesTest.hs b/tests/Numeric/Units/Dimensional/QuantitiesTest.hs
new file mode 100644
--- /dev/null
+++ b/tests/Numeric/Units/Dimensional/QuantitiesTest.hs
@@ -0,0 +1,132 @@
+module Numeric.Units.Dimensional.QuantitiesTest where
+
+import Numeric.Units.Dimensional.Prelude
+import qualified Prelude
+
+-- These definitions simply verify that the type synonyms are
+-- consistent with the appropriate units from table 2. If the
+-- definitions compile the type synonyms are good.
+
+x1 :: Area Double
+x1 = 1 *~ meter ^ pos2
+x2 :: Volume Double
+x2 = 1 *~ meter ^ pos3
+x3 :: Velocity Double
+x3 = 1 *~ (meter / second)
+x4 :: Acceleration Double
+x4 = 1 *~ (meter / second ^ pos2)
+x5 :: WaveNumber Double
+x5 = 1 *~ meter ^ neg1
+x6 :: Density Double
+x6 = 1 *~ (kilo gram / meter ^ pos3)
+x7 :: SpecificVolume Double
+x7 = 1 *~ (meter ^ pos3 / kilo gram)
+x8 :: CurrentDensity Double
+x8 = 1 *~ (ampere / meter ^ pos2)
+x9 :: MagneticFieldStrength Double
+x9 = 1 *~ (ampere / meter)
+x10 :: Concentration Double
+x10 = 1 *~ (mole / meter ^ pos3)
+x11 :: Luminance Double
+x11 = 1 *~ (candela / meter ^ pos2)
+
+-- These definitions simply verify that the type synonyms are
+-- consistent with the appropriate units from table 3. If the
+-- definitions compile the type synonyms are good.
+
+y1 :: PlaneAngle Double
+y1 = 1 *~ (meter / meter)
+y2 :: SolidAngle Double
+y2 = 1 *~ (meter ^ pos2 / meter ^ pos2)
+y3 :: Frequency Double
+y3 = 1 *~ (one / second)
+y4 :: Force Double
+y4 = 1 *~ (meter * kilo gram / second ^ pos2)
+y5 :: Pressure Double
+y5 = 1 *~ (newton / meter ^ pos2)
+y6 :: Energy Double
+y6 = 1 *~ (newton * meter)
+y7 :: Power Double
+y7 = 1 *~ (joule / second)
+y8 :: ElectricCharge Double
+y8 = 1 *~ (second * ampere)
+y9 :: ElectricPotential Double
+y9 = 1 *~ (watt / ampere)
+y10 :: Capacitance Double
+y10 = 1 *~ (coulomb / volt)
+y11 :: ElectricResistance Double
+y11 = 1 *~ (volt / ampere)
+y12 :: ElectricConductance Double
+y12 = 1 *~ (ampere / volt)
+y13 :: MagneticFlux Double
+y13 = 1 *~ (volt * second)
+y14 :: MagneticFluxDensity Double
+y14 = 1 *~ (weber / meter ^ pos2)
+y15 :: Inductance Double
+y15 = 1 *~ (weber / ampere)
+y16 :: LuminousFlux Double
+y16 = 1 *~ (candela * steradian)
+y17 :: Illuminance Double
+y17 = 1 *~ (lumen / meter ^ pos2)
+y18 :: Activity Double
+y18 = 1 *~ (one / second)
+y19 :: AbsorbedDose Double
+y19 = 1 *~ (joule / kilo gram)
+y20 :: DoseEquivalent Double
+y20 = 1 *~ (joule / kilo gram)
+y21 :: CatalyticActivity Double
+y21 = 1 *~ (mole / second)
+
+-- Verification of table 4. If the definitions compile the type
+-- synonyms are good.
+
+z1 :: AngularVelocity Double
+z1 = 1 *~ (radian / second)
+z2 :: AngularAcceleration Double
+z2 = 1 *~ (radian / second ^ pos2)
+z3 :: DynamicViscosity Double
+z3 = 1 *~ (pascal * second)
+z4 :: MomentOfForce Double
+z4 = 1 *~ (newton * meter)
+z5 :: SurfaceTension Double
+z5 = 1 *~ (newton / meter)
+z6 :: HeatFluxDensity Double
+z6 = 1 *~ (watt / meter ^ pos2)
+z7 :: RadiantIntensity Double
+z7 = 1 *~ (watt / steradian)
+z8 :: Radiance Double
+z8 = 1 *~ (watt / (meter ^ pos2 * steradian))
+z9 :: HeatCapacity Double
+z9 = 1 *~ (joule / kelvin)
+z10 :: SpecificHeatCapacity Double
+z10 = 1 *~ (joule / (kilo gram * kelvin))
+z11 :: ThermalConductivity Double
+z11 = 1 *~ (watt / (meter * kelvin))
+z12 :: EnergyDensity Double
+z12 = 1 *~ (joule / meter ^ pos3)
+z13 :: ElectricFieldStrength Double
+z13 = 1 *~ (volt / meter)
+z14 :: ElectricChargeDensity Double
+z14 = 1 *~ (coulomb / meter ^ pos3)
+z15 :: ElectricFluxDensity Double
+z15 = 1 *~ (coulomb / meter ^ pos2)
+z16 :: Permittivity Double
+z16 = 1 *~ (farad / meter)
+z17 :: Permeability Double
+z17 = 1 *~ (henry / meter)
+z18 :: MolarEnergy Double
+z18 = 1 *~ (joule / mole)
+z19 :: MolarEntropy Double
+z19 = 1 *~ (joule / (mole * kelvin))
+z20 :: Exposure Double
+z20 = 1 *~ (coulomb / kilo gram)
+z21 :: AbsorbedDoseRate Double
+z21 = 1 *~ (gray / second)
+
+-- Other quantitites.
+mu :: GravitationalParameter Double
+mu = 398600.4418 *~ (kilo meter ^ pos3 / second ^ pos2)
+
+-- Dummy main function.
+main :: IO ()
+main = Prelude.putStrLn "If I compiled I'm OK!"
diff --git a/tests/Numeric/Units/Dimensional/Test.hs b/tests/Numeric/Units/Dimensional/Test.hs
new file mode 100644
--- /dev/null
+++ b/tests/Numeric/Units/Dimensional/Test.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE NoMonomorphismRestriction #-}
+
+module Numeric.Units.Dimensional.Test where
+
+import Numeric.Units.Dimensional.Prelude
+import qualified Prelude
+import Test.HUnit
+
+testPower :: Test
+testPower = TestLabel "Power test" $ TestList
+    [ TestCase $ ((9::Double) *~ one) @=? (3 *~ one) ^ pos2
+    , TestCase $ ((1::Double) *~ one) @=? (12.1231 *~ one) ^ zero
+    , TestCase $ ((0.25::Double) *~ one) @=? (2 *~ one) ^ neg2
+    ]
+
+testDimensionless :: Test
+testDimensionless = TestLabel "Dimensionless test" $ TestList
+    [ TestCase $ (3 Prelude.** 2::Double) *~ one @=? (3 *~ one) ** (2 *~ one)
+    ]
+
+testShow :: Test
+testShow = TestLabel "Test 'Show' instance" $ TestList
+    [ TestCase $ show ((1.0::Double) *~ one) @?= "1.0"
+    , TestCase $ show ((2.0::Double) *~ meter) @?= "2.0 m"
+    , TestCase $ show ((2.0::Double) *~ (meter / second)) @?= "2.0 m s^-1"
+    , TestCase $ show ((2.0::Double) *~ (meter ^ pos2 / second ^ pos2)) @?= "2.0 m^2 s^-2"
+    --, TestCase $ show (undefined :: DimRep DVelocity) @?= "m s^-1"
+    ]
+
+testOrdering :: Test
+testOrdering = TestLabel "Test 'Ord' instance" $ TestList
+    [ TestCase $ compare ((1 :: Integer) *~ one) (3 *~ one) @?= LT
+    , TestCase $ compare ((1 :: Double) *~ (kilo meter)) (1 *~ meter) @?= GT
+    , TestCase $ compare ((0 :: Double) *~ second) (_0) @?= EQ 
+    ]
+
+testNFromTo :: Test
+testNFromTo = TestLabel "Test enumeration function 'nFromTo'" $ TestList
+    [ TestCase $ nFromTo' _1 _6 0    @?= [_1, _6]
+    , TestCase $ nFromTo' _1 _6 (-1) @?= [_1, _6]
+    , TestCase $ nFromTo' _1 _3 1    @?= [_1, _2, _3]
+    , TestCase $ nFromTo' _1 _6 4    @?= [_1, _2, _3, _4, _5, _6]
+    , TestCase $ nFromTo' _5 _2 2    @?= [_5, _4, _3, _2]
+    , TestCase $ nFromTo' _0 _6 2    @?= [_0, _2, _4, _6]
+    , TestCase $ nFromTo' _6 _0 2    @?= [_6, _4, _2, _0]
+    , TestCase $ nFromTo' _1 _1 0    @?= [_1, _1]
+    , TestCase $ nFromTo' _0 _0 2    @?= [_0, _0, _0, _0]
+    ]
+  where
+    nFromTo' :: Dimensionless Double -> Dimensionless Double -> Int -> [Dimensionless Double]
+    nFromTo' = nFromTo
+
+-- Collect the test cases.
+tests :: Test
+tests = TestList
+    [ testPower
+    , testDimensionless
+    , testShow
+    , testOrdering
+    , testNFromTo
+    ]
+
+main :: IO Bool -- True means everything passed
+main = do
+         res <- runTestTT tests
+         return $ (errors res == 0) && (failures res == 0)
diff --git a/tests/Test.hs b/tests/Test.hs
new file mode 100644
--- /dev/null
+++ b/tests/Test.hs
@@ -0,0 +1,11 @@
+import qualified Numeric.Units.Dimensional.Test
+import qualified Numeric.Units.Dimensional.QuantitiesTest
+import System.Exit
+
+main :: IO ()
+main = do
+         Numeric.Units.Dimensional.QuantitiesTest.main
+         ok <- Numeric.Units.Dimensional.Test.main
+         if ok
+           then exitSuccess
+           else exitFailure
