Commits

Thijs Alkemade committed 59783ba Merge

Merged default into TypeNats.

Comments (0)

Files changed (14)

 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE InstanceSigs #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE StandaloneDeriving #-}
 
 -- |Module defining values with dimensions and units, and mathematical operations on those.
 module UnitTyped (
-        Convertible(..), Convertible'(..), Unit(..),
+        Convertible(..), Convertible'(..), U(..),
         Value(..), ValueProxy, ValueProxy', proxy',
 
         Count,
         POne, PTwo, PThree, PFour, PFive, PSix,
         NOne, NTwo, NThree, NFour,
 
-        coerce, as, to, one, mkVal, val, mapVal, (|*|), (|/|), (|+|), (|-|),
+        coerce, as, to, one, mkVal, val, (|*|), (|/|), (|+|), (|-|),
         (*|), (|*), (|/), (/|), (|+), (+|), (|-), (-|),
         (|==|), (|<=|), (|<|), (|>=|), (|>|),
 
+        dimension, unit,
+
         square, cubic
 ) where
 
 import GHC.TypeLits
+import Control.Applicative
+import Data.Monoid
+import Data.Foldable
+import Data.Traversable
+import qualified Data.Vector.Generic as VG
+import qualified Data.Vector.Generic.Mutable as VGM
+import qualified Data.Vector.Unboxed as VU
+
+import qualified Data.Map as M
+import Data.Typeable
 
 -- |Type level integers. I a b represents a - b.
 data Number = I Nat Nat
 instance (MapNull (MapMerge map1 (MapNeg map2))) => MapEq map1 map2 where
 
 -- |A value tagged with its dimension a and unit b.
-data Value f (a :: [(*, Number)]) (b :: [(*, Number)]) = Value f
+newtype Value (a :: [(*, Number)]) (b :: [(*, Number)]) f = Value f
 -- |Used as fake argument for the 'Convertible' class.
 data ValueProxy (a :: [(*, Number)]) b
 -- |Used as fake argument for the 'Convertible'' class.
 data ValueProxy' (a :: [(*, Number)]) (b :: [(*, Number)])
 
 -- |Obtain a 'ValueProxy'' from a 'Value'.
-proxy' :: (Convertible' a b) => Value f a b -> ValueProxy' a b
+proxy' :: (Convertible' a b) => Value a b f -> ValueProxy' a b
 proxy' _ = error "proxy'"
 
+class Dimension a where
+    dimension :: Value a b f -> M.Map TypeRep Integer
+
+instance Dimension '[] where
+    dimension _ = M.empty
+
+instance (Typeable dim, Dimension rest, SingI value) => Dimension ('(dim, value) ': rest) where
+    dimension :: forall (b :: [(*, Number)]) f . Value ('(dim, value) ': rest) b f -> M.Map TypeRep Integer
+    dimension _ = M.insert (typeOf (error "typeOf" :: dim)) (fromSing (sing :: Sing value)) (dimension (undefined :: Value rest b f))
+
+class Unit b where
+    unit :: Value a b f -> M.Map TypeRep Integer
+
+instance Unit '[] where
+    unit _ = M.empty
+
+instance (Typeable uni, Unit rest, SingI value) => Unit ('(uni, value) ': rest) where
+    unit :: forall (a :: [(*, Number)]) f . Value a ('(uni, value) ': rest) f -> M.Map TypeRep Integer
+    unit _ = M.insert (typeOf (error "typeOf" :: uni)) (fromSing (sing :: Sing value)) (unit (undefined :: Value a rest f))
+
 -- |Convertible is a class that models the fact that the base unit 'b' has dimension 'a'.
 class Convertible (a :: [(*, Number)]) b | b -> a where
         -- |The multiplication factor to convert this base unit between other units in the same dimension.
         showunit :: ValueProxy a b -> String
 
 -- |Shorthand to create a composed unit containing just one base unit.
-type Unit a = '[ '(a, P 1) ]
+type U a = '[ '(a, P 1) ]
 
 -- |Convertible' is a class that models the fact that the composed unit 'b' has dimension 'a'.
 class Convertible' (a :: [(*, Number)]) (b :: [(*, Number)]) where
         showunit' :: ValueProxy' a b -> String
 
 instance (MapNull a, MapNull b) => Convertible' a b where
+        {-# INLINE factor' #-}
         factor' _ = 1
+        {-# INLINE showunit' #-}
         showunit' _ = ""
 
 instance (SingI value, Convertible' rec_dimension rest,
           rec_dimension ~ MapMerge times_neg_unit_dimension dimension,
           Convertible unit_dimension unit) => Convertible' dimension ('(unit, value) ': rest) where
         factor' _ = let
-                                        rec = factor' (undefined :: ValueProxy' rec_dimension rest)
-                                in rec * ((factor (undefined :: ValueProxy unit_dimension unit)) ^^ (fromSing (sing :: Sing value)))
+                        rec = factor' (undefined :: ValueProxy' rec_dimension rest)
+                    in rec * ((factor (undefined :: ValueProxy unit_dimension unit)) ^^ (fromSing (sing :: Sing value)))
         showunit' _ = let
-                                        rec = showunit' (undefined :: ValueProxy' rec_dimension rest)
-                                        power = fromSing (sing :: Sing value)
-                                  in (if null rec then "" else rec) ++ (if (not $ null rec) && (power /= 0) then "⋅" else "") ++ (if power /= 0 then (showunit (undefined :: ValueProxy a'' unit)) ++ if power /= 1 then map toSuperScript $ show power else "" else "")
+                          rec = showunit' (undefined :: ValueProxy' rec_dimension rest)
+                          power = fromSing (sing :: Sing value)
+                      in rec
+                          ++ (if (not $ null rec) && (power /= 0) then "⋅" else "")
+                          ++ (if power /= 0
+                              then (showunit (undefined :: ValueProxy a'' unit))
+                                    ++ if power /= 1
+                                       then map toSuperScript $ show power
+                                       else ""
+                              else "")
 
+toSuperScript :: Char -> Char
 toSuperScript '0' = '\8304'
 toSuperScript '1' = '\185'
 toSuperScript '2' = '\178'
 toSuperScript '-' = '\8315'
 toSuperScript x = x
 
-instance (Fractional f, Show f, Convertible' a b) => Show (Value f a b) where
+instance (Fractional f, Show f, Convertible' a b) => Show (Value a b f) where
         show u = show (val u) ++ " " ++ showunit' (proxy' u)
 
 -- |coerce something of a specific dimension into any other unit in the same dimension.
 --
 -- >>> coerce (120 *| meter / second) (kilo meter / hour)
 -- 432.0 km/h
-coerce :: (Convertible' a b, Convertible' c d, Fractional f, MapEq a c) => Value f a b -> Value f c d -> Value f c d
-coerce u _ = let result = mkVal (factor' (proxy' u) * val u / factor' (proxy' result)) in result
+coerce :: (Convertible' a b, Convertible' c d, Fractional f, MapEq a c) => Value a b f -> Value c d f -> Value c d f
+{-# INLINE[1] coerce #-}
+coerce u into = mkVal (factor' (proxy' u) * val u / factor' (proxy' into))
+
+{-# RULES
+"coerce/id" [10] forall (x :: Value a b f) (u :: Value a b f) . coerce u x = u
+"coerce/twice" [10] forall (x :: Value a b f) (y :: Value a d f) (u :: Value a i f) . coerce (coerce u y) x = coerce u x
+"coerce/twice2" [10] forall (x :: Value a b f) (y :: Value a d f) (u :: Value a i f) . coerce u (coerce y x) = coerce u x
+  #-}
 
 infixl 5 `as`
 
 -- |Shorthand for 'coerce'.
-as :: (Convertible' a b, Convertible' c d, Fractional f, MapEq a c) => Value f a b -> Value f c d -> Value f c d
+as :: (Convertible' a b, Convertible' c d, Fractional f, MapEq a c) => Value a b f -> Value c d f -> Value c d f
+{-# INLINE[20] as #-}
 as = coerce
 
 -- |Shorthand for 'flip' 'coerce'
-to :: (Convertible' a b, Convertible' c d, Fractional f, MapEq a c) => Value f c d -> Value f a b -> Value f c d
+to :: (Convertible' a b, Convertible' c d, Fractional f, MapEq a c) => Value c d f -> Value a b f -> Value c d f
+{-# INLINE[20] to #-}
 to = flip coerce
 
 infixl 7 |*|, |/|
 
 -- |Multiply two values, constructing a value with as dimension the product of the dimensions,
 -- and as unit the multplication of the units.
-(|*|) :: (Fractional f, Convertible' a b, Convertible' c d) => Value f a b -> Value f c d -> Value f (MapMerge a c) (MapMerge b d)
+(|*|) :: (Fractional f, Convertible' a b, Convertible' c d) => Value a b f -> Value c d f -> Value (MapMerge a c) (MapMerge b d) f
+{-# INLINE (|*|) #-}
 a |*| b = mkVal (val a * val b)
 
 -- |Divide two values, constructing a value with as dimension the division of the dimension of the lhs by the dimension of the rhs,
 -- and the same for the units.
-(|/|), per :: (Fractional f, Convertible' a b, Convertible' c d) => Value f a b -> Value f c d -> Value f (MapMerge a (MapNeg c)) (MapMerge b (MapNeg d))
+(|/|), per :: (Fractional f, Convertible' a b, Convertible' c d) => Value a b f -> Value c d f -> Value (MapMerge a (MapNeg c)) (MapMerge b (MapNeg d)) f
+{-# INLINE (|/|) #-}
 a |/| b = mkVal (val a / val b)
+{-# INLINE per #-}
 per = (|/|)
 
 -- |Add two values with matching dimensions. Units are automatically resolved. The result will have the same unit as the lhs.
-(|+|) :: (Fractional f, Convertible' a b, Convertible' c d, MapEq c a) => Value f a b -> Value f c d -> Value f a b
-a |+| b = mkVal (val a + val (coerce b a))
+(|+|) :: (Fractional f, Convertible' a b, Convertible' c d, MapEq c a) => Value a b f -> Value c d f -> Value a b f
+{-# INLINE (|+|) #-}
+a |+| b = fmap (+ val (coerce b a)) a
 
 -- |Subtract two values with matching dimensions. Units are automatically resolved. The result will have the same unit as the lhs.
-(|-|) :: (Fractional f, Convertible' a b, Convertible' c d, MapEq c a) => Value f a b -> Value f c d -> Value f a b
-a |-| b = mkVal (val a - val (coerce b a))
+(|-|) :: (Fractional f, Convertible' a b, Convertible' c d, MapEq c a) => Value a b f -> Value c d f -> Value a b f
+{-# INLINE (|-|) #-}
+a |-| b = fmap (\x -> x - val (coerce b a)) a
 
 infixl 9 *|, |*, |/, /|
 infixl 8 +|, |+, -|, |-
 
 -- |Multiply a scalar by a unit.
-(*|) :: (Convertible' a b, Fractional f) => f -> Value f a b -> Value f a b
-d *| u = mkVal (d * val u)
+(*|) :: (Convertible' a b, Fractional f) => f -> Value a b f -> Value a b f
+{-# INLINE (*|) #-}
+d *| u = fmap (d*) u
 
 -- |Multiply a unit by a scalar.
-(|*) :: (Convertible' a b, Fractional f) => Value f a b -> f -> Value f a b
-u |* d = mkVal (val u * d)
+(|*) :: (Convertible' a b, Fractional f) => Value a b f -> f -> Value a b f
+{-# INLINE (|*) #-}
+u |* d = fmap (*d) u
 
 -- |Divide a scalar by a unit.
-(/|) :: (Convertible' a b, Fractional f) => f -> Value f a b -> Value f (MapNeg a) (MapNeg b)
+(/|) :: (Convertible' a b, Fractional f) => f -> Value a b f -> Value (MapNeg a) (MapNeg b) f
+{-# INLINE (/|) #-}
 d /| u = mkVal (d / val u)
 
 -- |Divide a unit by a scalar.
-(|/) :: (Convertible' a b, Fractional f) => Value f a b -> f -> Value f a b
-u |/ d = mkVal (val u / d)
+(|/) :: (Convertible' a b, Fractional f) => Value a b f -> f -> Value a b f
+{-# INLINE (|/) #-}
+u |/ d = fmap (/d) u
 
 -- |Add a unit to a scalar.
-(+|) :: (Convertible' a b, Fractional f) => f -> Value f a b -> Value f a b
-d +| u = mkVal (d + val u)
+(+|) :: (Convertible' a b, Fractional f) => f -> Value a b f -> Value a b f
+{-# INLINE (+|) #-}
+d +| u = fmap (d+) u
 
 -- |Add a scalar to a unit.
-(|+) :: (Convertible' a b, Fractional f) => Value f a b -> f -> Value f a b
-u |+ d = mkVal (val u + d)
+(|+) :: (Convertible' a b, Fractional f) => Value a b f -> f -> Value a b f
+{-# INLINE (|+) #-}
+u |+ d = fmap (+d) u
 
 -- |Subtract a unit from a scalar.
-(-|) :: (Convertible' a b, Fractional f) => f -> Value f a b -> Value f a b
-d -| u = mkVal (d - val u)
+(-|) :: (Convertible' a b, Fractional f) => f -> Value a b f -> Value a b f
+{-# INLINE (-|) #-}
+d -| u = fmap (d-) u
 
 -- |Subtract a scalar from a unit.
-(|-) :: (Convertible' a b, Fractional f) => Value f a b -> f -> Value f a b
-u |- d = mkVal (val u - d)
+(|-) :: (Convertible' a b, Fractional f) => Value a b f -> f -> Value a b f
+{-# INLINE (|-) #-}
+u |- d = fmap (\x -> x - d) u
 
 -- |Create a new value with given scalar as value.
-mkVal :: (Fractional f) => f -> Value f a b
+mkVal :: f -> Value a b f
+{-# INLINE mkVal #-}
 mkVal = Value
 
 -- |Obtain the value of a value wrapped in a type.
-val :: (Fractional f) => Value f a b -> f
+val :: Value a b f -> f
+{-# INLINE val #-}
 val (Value f) = f
 
--- |Map over values. The 'Fractional' constraints make it impossible to define a 'Functor' instance, therefore this.
-mapVal :: (Fractional f, Fractional g) => (f -> g) -> Value f a b -> Value g a b
-mapVal f = mkVal . f . val
+deriving instance (Enum f) => Enum (Value a b f)
+
+deriving instance (Eq f) => Eq (Value a b f)
+
+instance Functor (Value a b) where
+    {-# INLINE fmap #-}
+    fmap f = mkVal . f . val
+
+instance Monad (Value a b) where
+    x >>= f = f $ val x
+    return = mkVal
+
+instance Applicative (Value a b) where
+    pure = mkVal
+    f <*> x = mkVal $ (val f) (val x)
+
+instance (Convertible' a b, Fractional f) => Monoid (Value a b f) where
+    mempty = mkVal 0
+    mappend = (|+|)
+
+instance Foldable (Value a b) where
+    foldMap f = f . val
+
+instance Traversable (Value a b) where
+    traverse f x = mkVal <$> (f $ val x)
+
+deriving instance VG.Vector VU.Vector f => VG.Vector VU.Vector (Value a b f) 
+deriving instance VGM.MVector VU.MVector f => VGM.MVector VU.MVector (Value a b f) 
+deriving instance VU.Unbox f => VU.Unbox (Value a b f) 
+
+    
 
 -- |A wrapped value with scalar value 1.
-one :: (Fractional f, Convertible' a b) => Value f a b
+one :: (Fractional f, Convertible' a b) => Value a b f
+{-# INLINE one #-}
 one = mkVal 1
 
 -- |Calculate the square of a value. Identical to pow2, reads better on units:
 --
 -- >>> 100 *| square meter `as` square yard
 -- 119.59900463010803 yd⋅yd⋅#
-square :: (Fractional f, Convertible' c d) => Value f c d -> Value f (MapMerge c c) (MapMerge d d)
+square :: (Fractional f, Convertible' c d) => Value c d f -> Value (MapMerge c c) (MapMerge d d) f
+{-# INLINE square #-}
 square x = x |*| x
 
 -- |Calculate the third power of a value. Identical to pow3, reads better on units:
 --
 -- >>> 1 *| cubic inch `as` mili liter
 -- 16.387063999999995 mL
-cubic :: (Fractional f, Convertible' t t1, Convertible' c d, MapMerge d d ~ t1, MapMerge c c ~ t) => Value f c d -> Value f (MapMerge (MapMerge c c) c) (MapMerge (MapMerge d d) d)
+cubic :: (Fractional f, Convertible' t t1, Convertible' c d, MapMerge d d ~ t1, MapMerge c c ~ t) => Value c d f -> Value (MapMerge (MapMerge c c) c) (MapMerge (MapMerge d d) d) f
+{-# INLINE cubic #-}
 cubic x = x |*| x |*| x
 
-wrapB :: (Convertible' a b, Convertible' c d, MapEq c a) => (Rational -> Rational -> Bool) -> Value Rational a b -> Value Rational c d -> Bool
+wrapB :: (Convertible' a b, Convertible' c d, MapEq c a) => (Rational -> Rational -> Bool) -> Value a b Rational -> Value c d Rational -> Bool
+{-# INLINE wrapB #-}
 wrapB op a b = op (val a) (val $ coerce b a)
 
 infixl 4 |==|, |<|, |>|, |<=|, |>=|
 
-(|==|), (|<|), (|>|), (|<=|), (|>=|) :: (Convertible' a b, Convertible' c d, MapEq c a) => Value Rational a b -> Value Rational c d -> Bool
+(|==|), (|<|), (|>|), (|<=|), (|>=|) :: (Convertible' a b, Convertible' c d, MapEq c a) => Value a b Rational -> Value c d Rational -> Bool
 -- |'==' for values. Only defined for values with rational contents. Can be used on any two values with the same dimension.
+{-# INLINE (|==|) #-}
 (|==|) = wrapB (==)
 -- |'<' on values. Only defined for values with rational contents. Can be used on any two values with the same dimension.
+{-# INLINE (|<|) #-}
 (|<|) = wrapB (<)
 -- |'<=' on values. Only defined for values with rational contents. Can be used on any two values with the same dimension.
+{-# INLINE (|<=|) #-}
 (|<=|) = wrapB (<=)
 -- |'>' on values. Only defined for values with rational contents. Can be used on any two values with the same dimension.
+{-# INLINE (|>|) #-}
 (|>|) = wrapB (>)
 -- |'>=' on values. Only defined for values with rational contents. Can be used on any two values with the same dimension.
+{-# INLINE (|>=|) #-}
 (|>=|) = wrapB (>=)
 
 ----

src/UnitTyped/Bytes.hs

 import UnitTyped.SI.Derived
 import UnitTyped.SI
 
+import Data.Typeable
+
 ----
 -- Data
 ----
 
 -- |An of amount of data.
 data Data
+	deriving Typeable
 -- |The dimension representing @Data^1@.
 type DataDimension = '[ '(Data, POne) ]
 
 -- |A byte of data.
 data Byte
+	deriving Typeable
 
 instance Convertible DataDimension Byte where
 	factor _ = 1
 
 -- |A bit of data.
 data Bit
+	deriving Typeable
 
 instance Convertible DataDimension Bit where
 	factor _ = 0.125
 --
 
 -- |One byte.
-byte :: (Fractional f) => Value f DataDimension (Unit Byte)
+byte :: (Fractional f) => Value DataDimension (U Byte) f
 byte = one
 
 -- |One bit.
-bit :: (Fractional f) => Value f DataDimension (Unit Bit)
+bit :: (Fractional f) => Value DataDimension (U Bit) f
 bit = one

src/UnitTyped/NoPrelude.hs

 import UnitTyped.SI.Derived.Count
 
 import qualified Prelude
-import Prelude (Show(..), Fractional, Floating, ($), (.), (++), Double, const, Bool(..), otherwise, undefined, String(..), error)
+import Prelude (Show(..), Fractional, Floating, ($), (.), (++), Double, const, Bool(..), otherwise, undefined, String(..), error, fmap)
 
 infixl 6 +, -
 infixl 7 *, /
 
 -- |See '|*|'
-(*) :: (Fractional f, Convertible' a b, Convertible' c d) => Value f a b -> Value f c d -> Value f (MapMerge a c) (MapMerge b d)
+(*) :: (Fractional f, Convertible' a b, Convertible' c d) => Value a b f -> Value c d f -> Value (MapMerge a c) (MapMerge b d) f
 (*) = (|*|)
 
 -- |See '|/|'
-(/) :: (Fractional f, Convertible' a b, Convertible' c d) => Value f a b -> Value f c d -> Value f (MapMerge a (MapNeg c)) (MapMerge b (MapNeg d))
+(/) :: (Fractional f, Convertible' a b, Convertible' c d) => Value a b f -> Value c d f -> Value (MapMerge a (MapNeg c)) (MapMerge b (MapNeg d)) f
 (/) = (|/|)
 
 -- |See '|+|'
-(+) :: (Fractional f, Convertible' a b, Convertible' c d, MapEq c a) => Value f a b -> Value f c d -> Value f a b
+(+) :: (Fractional f, Convertible' a b, Convertible' c d, MapEq c a) => Value a b f -> Value c d f -> Value a b f
 (+) = (|+|)
 
 -- |See '|-|'
-(-) :: (Fractional f, Convertible' a b, Convertible' c d, MapEq c a) => Value f a b -> Value f c d -> Value f a b
+(-) :: (Fractional f, Convertible' a b, Convertible' c d, MapEq c a) => Value a b f -> Value c d f -> Value a b f
 (-) = (|-|)
 
-wrap1 :: (Floating f, Convertible' '[] b) => (f -> f) -> Value f '[] b -> Value f '[] '[]
+wrap1 :: (Floating f, Convertible' '[] b) => (f -> f) -> Value '[] b f -> Value '[] '[] f
 wrap1 op v = op (val $ coerce v rad) *| one
 
-sin, cos, tan :: (Floating f, Convertible' '[] b) => Value f '[] b -> Value f '[] '[]
+sin, cos, tan :: (Floating f, Convertible' '[] b) => Value '[] b f -> Value '[] '[] f
 -- |Calculate the sinus of a value. Works on 'Degree' and 'Radian'.
 sin = wrap1 Prelude.sin
 -- |Calculate the cosinus of a value. Works on 'Degree' and 'Radian'.
 -- |Calculate the tangens of a value. Works on 'Degree' and 'Radian'.
 tan = wrap1 Prelude.tan
 
-wrap2 :: (Floating f) => (f -> f) -> Value f '[] '[] -> Value f '[] (Unit Radian)
+wrap2 :: (Floating f) => (f -> f) -> Value '[] '[] f -> Value '[] (U Radian) f
 wrap2 op v = op (val v) *| one
 
-asin, acos, atan :: (Floating f) => Value f '[] '[] -> Value f '[] (Unit Radian)
+asin, acos, atan :: (Floating f) => Value '[] '[] f -> Value '[] (U Radian) f
 -- |Calculate the arcsinus of a value. Always computes 'Radian's.
 asin = wrap2 Prelude.asin
 -- |Calculate the arccosinus of a value. Always computes 'Radian's.
 
 infixl 5 ==, <, <=, >, >=
 
-(==), (<), (<=), (>), (>=) :: (Convertible' a b, Convertible' c d, MapEq c a) => Value Prelude.Rational a b -> Value Prelude.Rational c d -> Bool
+(==), (<), (<=), (>), (>=) :: (Convertible' a b, Convertible' c d, MapEq c a) => Value a b Prelude.Rational -> Value c d Prelude.Rational -> Bool
 -- |See '|==|'
 (==) = (|==|)
 -- |See '|<|'
 (>=) = (|>=|)
 
 -- |Obtain the 'Prelude.floor' of a value.
-floor :: (Prelude.RealFrac f) => Value f a b -> Value f a b
-floor = mapVal (Prelude.fromInteger . Prelude.floor)
+floor :: (Prelude.RealFrac f) => Value a b f -> Value a b f
+floor = fmap (Prelude.fromInteger . Prelude.floor)
 
 -- |Obtain @x - floor x@ of a value.
-diff :: (Convertible' a b, Prelude.RealFrac f) => Value f a b -> Value f a b
+diff :: (Convertible' a b, Prelude.RealFrac f) => Value a b f -> Value a b f
 diff x = x |-| (floor x)
 
 -- |Obtain the 'Prelude.abs' of a value.
-abs :: (Fractional f) => Value f a b -> Value f a b
-abs = mapVal Prelude.abs
+abs :: (Fractional f) => Value a b f -> Value a b f
+abs = fmap Prelude.abs
 -- |Module definig all SI units and their dimensions.
 module UnitTyped.SI where
 
+import Data.Typeable
 import UnitTyped
 
--- |Unit for moles. Officially, this is a SI unit, but we definite it in terms of 'Count'.
+-- |U for moles. Officially, this is a SI unit, but we definite it in terms of 'Count'.
 data Mole
+	deriving Typeable
 
 instance Convertible '[] Mole where
 	factor _ = 6.0221417930e23
 
 -- |Dimension of length.
 data Length
+	deriving Typeable
 -- |The dimension defining @Length^1@.
 type LengthDimension = '[ '(Length, POne) ]
 
 
 -- |The SI unit for 'Length': meter (m).
 data Meter
+	deriving Typeable
 
 instance Convertible LengthDimension Meter where
 	factor _ = 1
 
 -- |Dimension of time.
 data Time
+	deriving Typeable
 -- |The dimension defining @Time^1@.
 type TimeDimension = '[ '(Time, POne) ]
 
 
 -- |The SI unit for 'Time': second (s).
 data Second
+	deriving Typeable
 
 instance Convertible TimeDimension Second where
 	factor _ = 1
 
 -- |Dimension of mass.
 data Mass
+	deriving Typeable
 -- |The dimension defining @Mass^1@.
 type MassDimension = '[ '(Mass, POne) ]
 
 
 -- |The SI unit for 'Mass' is officially kilogram, but we define grams (g) here, so @kilo gram@ will work when using 'UnitTyped.SI.Meta'.
 data Gram
+	deriving Typeable
 
 instance Convertible MassDimension Gram where
 	factor _ = 0.001
 
 -- |Dimension of temperature.
 data Temperature
+	deriving Typeable
 -- |The dimension defining @Temperature^1@.
 type TemperatureDimension = '[ '(Temperature, POne) ]
 
 
 -- |The SI unit for 'Temperature': Kelvin (K).
 data Kelvin
+	deriving Typeable
 
 instance Convertible TemperatureDimension Kelvin where
 	factor _ = 1
 
 -- |Dimension of electric current.
 data Current
+	deriving Typeable
 -- |The dimension defining @Current^1@.
 type CurrentDimension = '[ '(Current, POne) ]
 
 
 -- |The SI unit for 'Current': ampere (A).
 data Ampere
+	deriving Typeable
 
 instance Convertible CurrentDimension Ampere where
 	factor _ = 1
 
 -- |Dimension of luminous intensity.
 data Luminous
+	deriving Typeable
 -- |The dimension defining @Luminous^1@.
 type LuminousDimension = '[ '(Luminous, POne) ]
 
 
 -- |The SI unit for 'Luminous' intensity: candela (cd).
 data Candela
+	deriving Typeable
 
 instance Convertible LuminousDimension Candela where
 	factor _ = 1
 ----
 
 -- |One thing (#).
-count :: (Fractional f) => Value f '[] '[]
+count :: (Fractional f) => Value '[] '[] f
 count = one
 
 -- |One mole (mol).
-mole :: (Fractional f) => Value f '[] '[]
+mole :: (Fractional f) => Value '[] '[] f
 mole = one
 
 --
 
 -- |One meter (m).
-meter :: (Fractional f) => Value f LengthDimension (Unit Meter)
+meter :: (Fractional f) => Value LengthDimension (U Meter) f
 meter = one
 
 --
 
 -- |One second (s).
-second :: (Fractional f) => Value f TimeDimension (Unit Second)
+second :: (Fractional f) => Value TimeDimension (U Second) f
 second = one
 
 --
 
 -- |One gram (g).
-gram :: (Fractional f) => Value f MassDimension (Unit Gram)
+gram :: (Fractional f) => Value MassDimension (U Gram) f
 gram = one
 
 --
 
 -- |One Kelvin (K).
-kelvin :: (Fractional f) => Value f TemperatureDimension (Unit Kelvin)
+kelvin :: (Fractional f) => Value TemperatureDimension (U Kelvin) f
 kelvin = one
 
 --
 
 -- |One ampere (A).
-ampere :: (Fractional f) => Value f CurrentDimension (Unit Ampere)
+ampere :: (Fractional f) => Value CurrentDimension (U Ampere) f
 ampere = one
 
 --
 
 -- |One candela (cd).
-candela :: (Fractional f) => Value f LuminousDimension (Unit Candela)
+candela :: (Fractional f) => Value LuminousDimension (U Candela) f
 candela = one

src/UnitTyped/SI/Constants.hs

 import UnitTyped.SI.Derived
 
 -- |π as the floating point value it has in the "Prelude".
-pi' :: (Fractional f, Floating f) => Value f '[] '[]
+pi' :: (Fractional f, Floating f) => Value '[] '[] f
 pi' = mkVal Prelude.pi
 
 -- |π as a rational value. Which it isn't. But we can pretend it is.
-pi :: (Fractional f) => Value f '[] '[]
+pi :: (Fractional f) => Value '[] '[] f
 pi = mkVal 3.1415926535897932384626433832795028841971
 
 -- |The speed of light
-c :: (Fractional f) => Value f Speed '[ '(Second, NOne), '(Meter, POne)]
+c :: (Fractional f) => Value Speed '[ '(Second, NOne), '(Meter, POne)] f
 c = mkVal 299792458
 
 -- |Planck constant
-h :: Fractional f => Value f '[ '(Time, NOne), '(Mass, POne), '(Length, PTwo) ] '[ '(Joule, POne), '(Second, POne) ]
+h :: Fractional f => Value '[ '(Time, NOne), '(Mass, POne), '(Length, PTwo) ] '[ '(Joule, POne), '(Second, POne) ] f
 h = mkVal 6.6260695729e-34
 
 -- |Reduced Planck constant
-hbar :: Fractional f => Value f '[ '(Time, NOne), '(Length, PTwo), '(Mass, POne)] '[ '(Second, POne), '(Joule, POne) ]
+hbar :: Fractional f => Value '[ '(Time, NOne), '(Length, PTwo), '(Mass, POne)] '[ '(Second, POne), '(Joule, POne) ] f
 hbar = coerce (h |/| (2 *| UnitTyped.SI.Constants.pi)) (error "hbar")
 
 -- |Atomic unit of charge (elementary charge)
-e :: (Fractional f) => Value f Charge (Unit Coulomb)
+e :: (Fractional f) => Value Charge (U Coulomb) f
 e = mkVal 1.6021765314e-19
 
 -- |Atomic unit of mass (electron mass)
-m_e :: (Fractional f) => Value f MassDimension (Unit (Kilo Gram))
+m_e :: (Fractional f) => Value MassDimension (U (Kilo Gram)) f
 m_e = mkVal 9.109382616e-31
 
 -- |Atomic unit of length
-a_0 :: (Fractional f) => Value f LengthDimension (Unit Meter)
+a_0 :: (Fractional f) => Value LengthDimension (U Meter) f
 a_0 = mkVal 0.529177210818e-10
 
 -- |Atomic unit of energy
-e_h :: (Fractional f) => Value f Energy (Unit Joule)
+e_h :: (Fractional f) => Value Energy (U Joule) f
 e_h = mkVal 4.3597441775e-18
 
 -- |Gas constant.
-r :: (Fractional f) => Value f '[ '(Temperature, NOne), '(Length, PTwo), '(Mass, POne), '(Time, NTwo) ] '[ '(Mole, NOne), '(Kelvin, NOne), '(Joule, POne) ]
+r :: (Fractional f) => Value '[ '(Temperature, NOne), '(Length, PTwo), '(Mass, POne), '(Time, NTwo) ] '[ '(Mole, NOne), '(Kelvin, NOne), '(Joule, POne) ] f
 r = mkVal 8.314462175
 
 -- |Gravitational constant
-g :: (Fractional f) => Value f '[ '(Time, NTwo), '(Length, PThree), '(Mass, NOne) ] '[ '(Second, NTwo), '(Meter, PThree), '((Kilo Gram), NOne) ]
+g :: (Fractional f) => Value '[ '(Time, NTwo), '(Length, PThree), '(Mass, NOne) ] '[ '(Second, NTwo), '(Meter, PThree), '((Kilo Gram), NOne) ] f
 g = mkVal 6.6738480e-11
 
 ---- |Planck mass

src/UnitTyped/SI/Derived.hs

 import UnitTyped.SI.Derived.Time
 import UnitTyped.SI.Meta
 
+import Data.Typeable
+
 import Data.Ratio
 
 -- |Speed. @Length^1 Time^-1@.
 
 -- |Derived unit of speed (kn).
 data Knot
+	deriving Typeable
 
 instance Convertible Speed Knot where
 	factor _ = 1852 / 3600
 type Force = '[ '(Time, NTwo), '(Mass, POne), '(Length, POne) ]
 -- |Unit of force (N).
 data Newton
+	deriving Typeable
 
 instance Convertible Force Newton where
 	factor _ = 1
 
 -- |Unit of energy (J).
 data Joule
+	deriving Typeable
 
 instance Convertible Energy Joule where
 	factor _ = 1
 
 -- |Unit of energy (eV).
 data Ev
+	deriving Typeable
 
 instance Convertible Energy Ev where
 	factor _ = 1.60217656535e-19
 
 -- |Unit of power (W).
 data Watt
+	deriving Typeable
 
 instance Convertible Power Watt where
 	factor _ = 1
 
 -- |Unit of pressure (Pa).
 data Pascal
+	deriving Typeable
 
 instance Convertible Pressure Pascal where
 	factor _ = 1
 
 -- |Unit of pressure (bar).
 data Bar
+	deriving Typeable
 
 instance Convertible Pressure Bar where
 	factor _ = 1e5
 
 -- |Unit of pressure (mmHg).
 data MmHg
+	deriving Typeable
 
 instance Convertible Pressure MmHg where
 	factor _ = 133.322
 
 -- |Unit of chage (C).
 data Coulomb
+	deriving Typeable
 
 instance Convertible Charge Coulomb where
 	factor _ = 1
 
 -- |Unit of potential (V).
 data Volt
+	deriving Typeable
 
 instance Convertible Potential Volt where
 	factor _ = 1
 
 -- |Unit of capacitance (F).
 data Farad
+	deriving Typeable
 
 instance Convertible Capacitance Farad where
 	factor _ = 1
 
 -- |Unit of resistance (Ω).
 data Ohm
+	deriving Typeable
 
 instance Convertible Resistance Ohm where
 	factor _ = 1
 
 -- |Unit of conductance (S).
 data Siemens
+	deriving Typeable
 
 instance Convertible Conductance Siemens where
 	factor _ = 1
 
 -- |Unit of magnetic flux (Wb).
 data Weber
+	deriving Typeable
 
 instance Convertible Flux Weber where
 	factor _ = 1
 
 -- |Unit of magnetic field strength (T).
 data Tesla
+	deriving Typeable
 
 instance Convertible FluxDensity Tesla where
 	factor _ = 1
 
 -- |Unit of Inductance (H).
 data Henry
+	deriving Typeable
 
 instance Convertible Inductance Henry where
 	factor _ = 1
 --
 
 -- |One knot.
-knot :: (Fractional f) => Value f Speed (Unit Knot)
+knot :: (Fractional f) => Value Speed (U Knot) f
 knot = one
 
 -- |One newton.
-newton :: (Fractional f) => Value f '[ '(Time, NTwo), '(Mass, POne), '(Length, POne)] (Unit Newton)
+newton :: (Fractional f) => Value '[ '(Time, NTwo), '(Mass, POne), '(Length, POne)] (U Newton) f
 newton = one
 
 -- |One joule.
-joule :: (Fractional f) => Value f Energy (Unit Joule)
+joule :: (Fractional f) => Value Energy (U Joule) f
 joule = one
 
 -- |One eV.
-eV :: (Fractional f) => Value f Energy (Unit Ev)
+eV :: (Fractional f) => Value Energy (U Ev) f
 eV = one
 
 -- |One kwh.
-kwh :: (Fractional f) => Value f Energy '[ '(Kilo Watt, POne), '(Hour, POne) ]
+kwh :: (Fractional f) => Value Energy '[ '(Kilo Watt, POne), '(Hour, POne) ] f
 kwh = one
 
 -- |One watt.
-watt :: (Fractional f) => Value f Power (Unit Watt)
+watt :: (Fractional f) => Value Power (U Watt) f
 watt = one
 
 -- |One pascal.
-pascal :: (Fractional f) => Value f Pressure (Unit Pascal)
+pascal :: (Fractional f) => Value Pressure (U Pascal) f
 pascal = one
 
 -- |One bar.
-bar :: (Fractional f) => Value f Pressure (Unit Bar)
+bar :: (Fractional f) => Value Pressure (U Bar) f
 bar = one
 
 -- |One mmHg.
-mmHg :: (Fractional f) => Value f Pressure (Unit MmHg)
+mmHg :: (Fractional f) => Value Pressure (U MmHg) f
 mmHg = one
 
 -- |One coulomb.
-coulomb :: (Fractional f) => Value f Charge (Unit Coulomb)
+coulomb :: (Fractional f) => Value Charge (U Coulomb) f
 coulomb = one
 
 -- |One volt.
-volt :: (Fractional f) => Value f Potential (Unit Volt)
+volt :: (Fractional f) => Value Potential (U Volt) f
 volt = one
 
 -- |One farad.
-farad :: (Fractional f) => Value f Capacitance (Unit Farad)
+farad :: (Fractional f) => Value Capacitance (U Farad) f
 farad = one
 
 -- |One ohm.
-ohm :: (Fractional f) => Value f Resistance (Unit Ohm)
+ohm :: (Fractional f) => Value Resistance (U Ohm) f
 ohm = one
 
 -- |One siemens.
-siemens :: (Fractional f) => Value f Conductance (Unit Siemens)
+siemens :: (Fractional f) => Value Conductance (U Siemens) f
 siemens = one
 
 -- |One weber.
-weber :: (Fractional f) => Value f Flux (Unit Weber)
+weber :: (Fractional f) => Value Flux (U Weber) f
 weber = one
 
 -- |One tesla.
-tesla :: (Fractional f) => Value f FluxDensity (Unit Tesla)
+tesla :: (Fractional f) => Value FluxDensity (U Tesla) f
 tesla = one
 
 -- |One henry.
-henry :: (Fractional f) => Value f Inductance (Unit Henry)
+henry :: (Fractional f) => Value Inductance (U Henry) f
 henry = one

src/UnitTyped/SI/Derived/Count.hs

 import UnitTyped
 import UnitTyped.SI
 
+import Data.Typeable
+
 ---
 -- Count
 ---
 
 -- |Percentage: 1% == 0.001
 data Percentage
+	deriving Typeable
 
 instance Convertible '[] Percentage where
 	factor _ = 0.01
 
 -- |Per mille: 1‰ == 0.001
 data Permil
+	deriving Typeable
 
 instance Convertible '[] Permil where
 	factor _ = 0.001
 
 -- |Parts per million: 1 ppm == 0.1^6
 data Ppm
+	deriving Typeable
 
 instance Convertible '[] Ppm where
 	factor _ = 0.1^6
 
 -- |Parts per billion: 1 ppb == 0.1^9
 data Ppb
+	deriving Typeable
 
 instance Convertible '[] Ppb where
 	factor _ = 0.1^9
 
 -- |Parts per trillion: 1 ppt == 0.1^12
 data Ppt
+	deriving Typeable
 
 instance Convertible '[] Ppt where
 	factor _ = 0.1^12
 
 -- |Angles are dimensionless, these are radians (rad).
 data Radian
+	deriving Typeable
 
 instance Convertible '[] Radian where
 	factor _ = 1
 
 -- |Angles are dimensionless, these are degrees (˚).
 data Degree
+	deriving Typeable
 
 instance Convertible '[] Degree where
 	factor _ = 3.141592653589793 / 180
 --
 
 -- |One percent (%).
-percent :: (Fractional f) => Value f '[] (Unit Percentage)
+percent :: (Fractional f) => Value '[] (U Percentage) f
 percent = one
 
 -- |One per mille (‰).
-permil :: (Fractional f) => Value f '[] (Unit Permil)
+permil :: (Fractional f) => Value '[] (U Permil) f
 permil = one
 
 -- |One part per million (ppm).
-ppm :: (Fractional f) => Value f '[] (Unit Ppm)
+ppm :: (Fractional f) => Value '[] (U Ppm) f
 ppm = one
 
 -- |One part per billion (ppb).
-ppb :: (Fractional f) => Value f '[] (Unit Ppb)
+ppb :: (Fractional f) => Value '[] (U Ppb) f
 ppb = one
 
 -- |One part per trillion (ppt).
-ppt :: (Fractional f) => Value f '[] (Unit Ppt)
+ppt :: (Fractional f) => Value '[] (U Ppt) f
 ppt = one
 
 -- |One rad (rad).
-rad :: (Fractional f) => Value f '[] (Unit Radian)
+rad :: (Fractional f) => Value '[] (U Radian) f
 rad = one
 
 -- |One degree (˚).
-deg :: (Fractional f) => Value f '[] (Unit Degree)
+deg :: (Fractional f) => Value '[] (U Degree) f
 deg = one

src/UnitTyped/SI/Derived/Length.hs

 import UnitTyped.SI.Derived
 import UnitTyped.SI.Meta
 
+import Data.Typeable
+
 import Data.Ratio
 
 ----
 
 -- |The international mile (mile).
 data Mile
+	deriving Typeable
 
 instance Convertible LengthDimension Mile where
 	factor _ = 1609.344
 
 -- |The international inch (in).
 data Inch
+	deriving Typeable
 
 instance Convertible LengthDimension Inch where
 	factor _ = 0.0254
 
 -- |The international yard (yd).
 data Yard
+	deriving Typeable
 
 instance Convertible LengthDimension Yard where
 	factor _ = 0.9144
 
 -- |The international foot (ft).
 data Foot
+	deriving Typeable
 
 instance Convertible LengthDimension Foot where
 	factor _ = 0.3048
 
 -- |Ångström, length unit for atoms and molecules (Å).
 data Ångström
+	deriving Typeable
 
 instance Convertible LengthDimension Ångström where
 	factor _ = 10e-10
 
 -- |Nautical miles (M).
 data NauticalMile
+	deriving Typeable
 
 instance Convertible LengthDimension NauticalMile where
 	factor _ = 1852
 
 -- |Area, often used in nuclear physics (b).
 data Barn
+	deriving Typeable
 
 instance Convertible AreaUnit Barn where
 	factor _ = 1e-28
 
 -- |Liter, unit of volume (L).
 data Liter
+	deriving Typeable
 
 instance Convertible VolumeUnit Liter where
 	factor _ = 0.001
 
 -- |Gallon, unit of volume (gallon).
 data Gallon
+	deriving Typeable
 
 instance Convertible VolumeUnit Gallon where
 	factor _ = 0.00454609
 
 -- |Fluid ounce, unit of volume (fl oz).
 data FluidOunce
+	deriving Typeable
 
 instance Convertible VolumeUnit FluidOunce where
 	factor _ = 0.0000284130625
 --
 
 -- |One mile (mile).
-mile :: (Fractional f) => Value f LengthDimension (Unit Mile)
+mile :: (Fractional f) => Value LengthDimension (U Mile) f
 mile = one
 
 -- |One inch (in).
-inch :: (Fractional f) => Value f LengthDimension (Unit Inch)
+inch :: (Fractional f) => Value LengthDimension (U Inch) f
 inch = one
 
 -- |One yard (yd).
-yard :: (Fractional f) => Value f LengthDimension (Unit Yard)
+yard :: (Fractional f) => Value LengthDimension (U Yard) f
 yard = one
 
 -- |One foot (ft).
-foot :: (Fractional f) => Value f LengthDimension (Unit Foot)
+foot :: (Fractional f) => Value LengthDimension (U Foot) f
 foot = one
 
-ångström, angstrom :: (Fractional f) => Value f LengthDimension (Unit Ångström)
+ångström, angstrom :: (Fractional f) => Value LengthDimension (U Ångström) f
 -- |One ångström (Å).
 ångström = one
 -- |One ångström, for those with bad UTF-8 support (Å).
 angstrom = one
 
 -- |One nautical mile (M).
-nautical_mile :: (Fractional f) => Value f LengthDimension (Unit NauticalMile)
+nautical_mile :: (Fractional f) => Value LengthDimension (U NauticalMile) f
 nautical_mile = one
 
 --
 
 -- |One barn (b).
-barn :: (Fractional f) => Value f AreaUnit (Unit Barn)
+barn :: (Fractional f) => Value AreaUnit (U Barn) f
 barn = one
 
 --
 
 -- |One liter (L).
-liter :: (Fractional f) => Value f VolumeUnit (Unit Liter)
+liter :: (Fractional f) => Value VolumeUnit (U Liter) f
 liter = one
 
 -- |One gallon (gallon).
-gallon :: (Fractional f) => Value f VolumeUnit (Unit Gallon)
+gallon :: (Fractional f) => Value VolumeUnit (U Gallon) f
 gallon = one
 
 -- |One fluid ounce (fl oz).
-fluid_ounce :: (Fractional f) => Value f VolumeUnit (Unit FluidOunce)
+fluid_ounce :: (Fractional f) => Value VolumeUnit (U FluidOunce) f
 fluid_ounce = one

src/UnitTyped/SI/Derived/Mass.hs

 import UnitTyped
 import UnitTyped.SI
 
+import Data.Typeable
+
 ----
 -- Mass
 ----
 
 -- |Pound, imperial unit of mass (lb).
 data Pound
+	deriving Typeable
 
 instance Convertible MassDimension Pound where
 	factor _ = 0.45359237
 --
 
 -- |One pound (lb).
-pound :: (Fractional f) => Value f MassDimension (Unit Pound)
+pound :: (Fractional f) => Value MassDimension (U Pound) f
 pound = one

src/UnitTyped/SI/Derived/Time.hs

 import UnitTyped.SI
 import UnitTyped.SI.Meta
 
+import Data.Typeable
+
 import Data.Ratio
 import qualified Data.Time as DT
 import qualified Data.Time.Clock as DTC
 
 -- |Hour (h).
 data Hour
+	deriving Typeable
 
 instance Convertible TimeDimension Hour where
 	factor _ = 3600
 
 -- |Minute (min.).
 data Minute
+	deriving Typeable
 
 instance Convertible TimeDimension Minute where
 	factor _ = 60
 
 -- |Day (day).
 data Day
+	deriving Typeable
 
 instance Convertible TimeDimension Day where
 	factor _ = 86400
 
 -- |Year (yr). This is an average year in the Gregorian calender (so 365.2425 days).
 data Year
+	deriving Typeable
 
 instance Convertible TimeDimension Year where
 	factor _ = 365.2425 * 24 * 60 * 60
 
 -- |Month (month). Average length of a month (365.2425 / 12).
 data Month
+	deriving Typeable
 
 instance Convertible TimeDimension Month where
 	factor _ = (365.2425 * 24 * 60 * 60) / 12
 
 -- |Julian year (a). This is an average year in the Julian calender (so 365.25 days). Still used in astronomy.
 data JulianYear
+	deriving Typeable
 
 instance Convertible TimeDimension JulianYear where
 	factor _ = 31557600
 
 -- |Frequency in Hertz. (Hz)
 data Hertz
+	deriving Typeable
 
 instance Convertible '[ '(Time, NOne) ] Hertz where
 	factor _ = 1
 --
 
 -- |One minute (min.).
-minute :: (Fractional f) => Value f TimeDimension (Unit Minute)
+minute :: (Fractional f) => Value TimeDimension (U Minute) f
 minute = one
 
 -- |One hour (h).
-hour :: (Fractional f) => Value f TimeDimension (Unit Hour)
+hour :: (Fractional f) => Value TimeDimension (U Hour) f
 hour = one
 
 -- |One day (day).
-day :: (Fractional f) => Value f TimeDimension (Unit Day)
+day :: (Fractional f) => Value TimeDimension (U Day) f
 day = one
 
 -- |One year (yr).
-year :: (Fractional f) => Value f TimeDimension (Unit Year)
+year :: (Fractional f) => Value TimeDimension (U Year) f
 year = one
 
 -- |One Julian year (a).
-julian_year :: (Fractional f) => Value f TimeDimension (Unit JulianYear)
+julian_year :: (Fractional f) => Value TimeDimension (U JulianYear) f
 julian_year = one
 
 -- |One month (month).
-month :: (Fractional f) => Value f TimeDimension (Unit Month)
+month :: (Fractional f) => Value TimeDimension (U Month) f
 month = one
 
 -- |One herz (Hz).
-hertz :: (Fractional f) => Value f '[ '(Time, NOne) ] (Unit Hertz)
+hertz :: (Fractional f) => Value '[ '(Time, NOne) ] (U Hertz) f
 hertz = one
 
 --
 -- Interaction with Data.Time
 
 -- |Convert a 'DT.DiffTime' into a value in seconds.
-fromDiffTime :: (Fractional f) => DT.DiffTime -> Value f TimeDimension (Unit Second)
+fromDiffTime :: (Fractional f) => DT.DiffTime -> Value TimeDimension (U Second) f
 fromDiffTime = mkVal . fromRational . toRational
 
 -- |Convert a 'DTC.NominalDiffTime' into a value in seconds.
-fromNominalDiffTime :: (Fractional f) => DTC.NominalDiffTime -> Value f TimeDimension (Unit Second)
+fromNominalDiffTime :: (Fractional f) => DTC.NominalDiffTime -> Value TimeDimension (U Second) f
 fromNominalDiffTime = mkVal . fromRational . toRational
 
 -- |Convert the number of seconds since a given 'DTC.UTCTime' into a value in seconds.
-since :: (Fractional f) => DTC.UTCTime -> IO (Value f TimeDimension (Unit Second))
+since :: (Fractional f) => DTC.UTCTime -> IO (Value TimeDimension (U Second) f)
 since time = do { t <- DTC.getCurrentTime
 		        ; return (fromNominalDiffTime (DTC.diffUTCTime t time) `as` second)
 		        }
 
 -- |Calculate the number of seconds since a given date and\/or time, parsed according to the first argument.
-since_str :: (Fractional f) => String -> String -> IO (Value f TimeDimension (Unit Second))
+since_str :: (Fractional f) => String -> String -> IO (Value TimeDimension (U Second) f)
 since_str fmt str = since (DTF.readTime SL.defaultTimeLocale fmt str)

src/UnitTyped/SI/Meta.hs

 	kibi, mebi, gibi, tebi, pebi, exbi, zebi, yobi
 ) where
 
+import Data.Typeable
 import UnitTyped.SI
 import UnitTyped
 
 
 -- |Create a unit 10^1 times an existing unit.
 data Deca a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Deca a b where
 	metafactor _ = 10
 
 -- |Create a unit 10^2 times an existing unit.
 data Hecto a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Hecto a b where
 	metafactor _ = 10^2
 
 -- |Create a unit 10^3 times an existing unit.
 data Kilo a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Kilo a b where
 	metafactor _ = 10^3
 
 -- |Create a unit 10^6 times an existing unit.
 data Mega a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Mega a b where
 	metafactor _ = 10^6
 
 -- |Create a unit 10^9 times an existing unit.
 data Giga a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Giga a b where
 	metafactor _ = 10^9
 
 -- |Create a unit 10^12 times an existing unit.
 data Tera a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Tera a b where
 	metafactor _ = 10^12
 
 -- |Create a unit 10^15 times an existing unit.
 data Peta a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Peta a b where
 	metafactor _ = 10^15
 
 -- |Create a unit 10^18 times an existing unit.
 data Exa a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Exa a b where
 	metafactor _ = 10^18
 
 -- |Create a unit 10^21 times an existing unit.
 data Zetta a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Zetta a b where
 	metafactor _ = 10^21
 
 -- |Create a unit 10^24 times an existing unit.
 data Yotta a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Yotta a b where
 	metafactor _ = 10^24
 
 -- |Create a unit 10^-1 times an existing unit.
 data Deci a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Deci a b where
 	metafactor _ = 0.1
 
 -- |Create a unit 10^-2 times an existing unit.
 data Centi a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Centi a b where
 	metafactor _ = 0.1^2
 
 -- |Create a unit 10^-3 times an existing unit.
 data Mili a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Mili a b where
 	metafactor _ = 0.1^3
 
 -- |Create a unit 10^-6 times an existing unit.
 data Micro a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Micro a b where
 	metafactor _ = 0.1^6
 
 -- |Create a unit 10^-9 times an existing unit.
 data Nano a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Nano a b where
 	metafactor _ = 0.1^9
 
 -- |Create a unit 10^-12 times an existing unit.
 data Pico a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Pico a b where
 	metafactor _ = 0.1^12
 
 -- |Create a unit 10^-15 times an existing unit.
 data Femto a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Femto a b where
 	metafactor _ = 0.1^15
 
 -- |Create a unit 10^-18 times an existing unit.
 data Atto a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Atto a b where
 	metafactor _ = 0.1^18
 
 -- |Create a unit 10^-21 times an existing unit.
 data Zepto a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Zepto a b where
 	metafactor _ = 0.1^21
 
 -- |Create a unit 10^-24 times an existing unit.
 data Yocto a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Yocto a b where
 	metafactor _ = 0.1^24
 
 -- |Create a unit 2^10 times an existing unit.
 data Kibi a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Kibi a b where
 	metafactor _ = 2 ^ 10
 
 -- |Create a unit 2^20 times an existing unit.
 data Mebi a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Mebi a b where
 	metafactor _ = 2 ^ 20
 
 -- |Create a unit 2^30 times an existing unit.
 data Gibi a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Gibi a b where
 	metafactor _ = 2 ^ 30
 
 -- |Create a unit 2^40 times an existing unit.
 data Tebi a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Tebi a b where
 	metafactor _ = 2 ^ 40
 
 -- |Create a unit 2^50 times an existing unit.
 data Pebi a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Pebi a b where
 	metafactor _ = 2 ^ 50
 
 -- |Create a unit 2^60 times an existing unit.
 data Exbi a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Exbi a b where
 	metafactor _ = 2 ^ 60
 
 -- |Create a unit 2^70 times an existing unit.
 data Zebi a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Zebi a b where
 	metafactor _ = 2 ^ 70
 
 -- |Create a unit 2^80 times an existing unit.
 data Yobi a
+	deriving Typeable
 
 instance (Convertible a b) => MetaUnit Yobi a b where
 	metafactor _ = 2 ^ 80
 ----
 
 -- |Take a unit and return one deca(unit).
-deca :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Deca b))
+deca :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Deca b)) f
+{-# INLINE deca #-}
 deca (Value x) = (Value x)
 
 -- |Take a unit and return one hecto(unit).
-hecto :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Hecto b))
+hecto :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Hecto b)) f
+{-# INLINE hecto #-}
 hecto (Value x) = (Value x)
 
 -- |Take a unit and return one kilo(unit).
-kilo :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Kilo b))
+kilo :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Kilo b)) f
+{-# INLINE kilo #-}
 kilo (Value x) = (Value x)
 
 -- |Take a unit and return one mega(unit).
-mega :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Mega b))
+mega :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Mega b)) f
 mega (Value x) = (Value x)
 
 -- |Take a unit and return one giga(unit).
-giga :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Giga b))
+giga :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Giga b)) f
 giga (Value x) = (Value x)
 
 -- |Take a unit and return one tera(unit).
-tera :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Tera b))
+tera :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Tera b)) f
 tera (Value x) = (Value x)
 
 -- |Take a unit and return one peta(unit).
-peta :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Peta b))
+peta :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Peta b)) f
 peta (Value x) = (Value x)
 
 -- |Take a unit and return one exa(unit).
-exa :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Exa b))
+exa :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Exa b)) f
 exa (Value x) = (Value x)
 
 -- |Take a unit and return one zetta(unit).
-zetta :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Zetta b))
+zetta :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Zetta b)) f
 zetta (Value x) = (Value x)
 
 -- |Take a unit and return one yotta(unit).
-yotta :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Yotta b))
+yotta :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Yotta b)) f
 yotta (Value x) = (Value x)
 
 -- |Take a unit and return one deci(unit).
-deci :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Deci b))
+deci :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Deci b)) f
 deci (Value x) = (Value x)
 
 -- |Take a unit and return one centi(unit).
-centi :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Centi b))
+centi :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Centi b)) f
 centi (Value x) = (Value x)
 
 -- |Take a unit and return one mili(unit).
-mili :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Mili b))
+mili :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Mili b)) f
 mili (Value x) = (Value x)
 
 -- |Take a unit and return one micro(unit).
-micro :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Micro b))
+micro :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Micro b)) f
 micro (Value x) = (Value x)
 
 -- |Take a unit and return one nano(unit).
-nano :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Nano b))
+nano :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Nano b)) f
 nano (Value x) = (Value x)
 
 -- |Take a unit and return one pico(unit).
-pico :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Pico b))
+pico :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Pico b)) f
 pico (Value x) = (Value x)
 
 -- |Take a unit and return one femto(unit).
-femto :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Femto b))
+femto :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Femto b)) f
 femto (Value x) = (Value x)
 
 -- |Take a unit and return one atto(unit).
-atto :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Atto b))
+atto :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Atto b)) f
 atto (Value x) = (Value x)
 
 -- |Take a unit and return one zepto(unit).
-zepto :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Zepto b))
+zepto :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Zepto b)) f
 zepto (Value x) = (Value x)
 
 -- |Take a unit and return one yocto(unit).
-yocto :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Yocto b))
+yocto :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Yocto b)) f
 yocto (Value x) = (Value x)
 
 --
 
 -- |Take a unit and return one kibi(unit).
-kibi :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Kibi b))
+kibi :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Kibi b)) f
 kibi (Value x) = (Value x)
 
 -- |Take a unit and return one mebi(unit).
-mebi :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Mebi b))
+mebi :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Mebi b)) f
 mebi (Value x) = (Value x)
 
 -- |Take a unit and return one gibi(unit).
-gibi :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Gibi b))
+gibi :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Gibi b)) f
 gibi (Value x) = (Value x)
 
 -- |Take a unit and return one tebi(unit).
-tebi :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Tebi b))
+tebi :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Tebi b)) f
 tebi (Value x) = (Value x)
 
 -- |Take a unit and return one pebi(unit).
-pebi :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Pebi b))
+pebi :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Pebi b)) f
 pebi (Value x) = (Value x)
 
 -- |Take a unit and return one exbi(unit).
-exbi :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Exbi b))
+exbi :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Exbi b)) f
 exbi (Value x) = (Value x)
 
 -- |Take a unit and return one zebi(unit).
-zebi :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Zebi b))
+zebi :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Zebi b)) f
 zebi (Value x) = (Value x)
 
 -- |Take a unit and return one yobi(unit).
-yobi :: (Convertible a b, Fractional f) => Value f a (Unit b) -> Value f a (Unit (Yobi b))
+yobi :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Yobi b)) f
 yobi (Value x) = (Value x)

src/UnitTyped/SI/Show.hs

 -- |Start a chain of units. For example:
 --
 -- > format_end second $ format minute $ format_start hour x
-format_start :: (Convertible' a b, Convertible' c d, MapEq a c) => Value Rational c d -> Value Rational a b -> (String, Value Rational c d)
+format_start :: (Convertible' a b, Convertible' c d, MapEq a c) => Value c d Rational -> Value a b Rational -> (String, Value c d Rational)
 format_start u v = format u ("", (NP.abs v) `as` u)
 
 -- |Add a unit in between 'format_start' and 'format_end'.
-format :: (Convertible' a b, Convertible' a d) => Value Rational a d -> (String, Value Rational a b) -> (String, Value Rational a d)
+format :: (Convertible' a b, Convertible' a d) => Value a d Rational -> (String, Value a b Rational) -> (String, Value a d Rational)
 format u (s, v) = let
 					  fl_v = NP.floor (coerce v u)
 					  str = (show $ numerator $ val $ fl_v) ++ " " ++ (showunit' $ proxy' u)
 			      in (s ++ (if val fl_v == 0 then "" else (if not $ null s then ", " else "") ++ str), NP.diff $ coerce v u)
 
 -- |End the chain of formatters.
-format_end :: (Convertible' a b, Convertible' a d) => Value Rational a d -> (String, Value Rational a b) -> String
+format_end :: (Convertible' a b, Convertible' a d) => Value a d Rational -> (String, Value a b Rational) -> String
 format_end u (s, v) = (s ++ (if val v == 0 then "" else ((if not $ null s then ", " else "") ++ (show $ fromRational $ val (coerce v u)) ++ " " ++ (showunit' $ proxy' u))))
 
 -- |Show a time range as years, days, hours, minutes, seconds and miliseconds.
-time_str :: (Convertible' a b, MapEq a TimeDimension) => Value Rational a b -> String
+time_str :: (Convertible' a b, MapEq a TimeDimension) => Value a b Rational -> String
 time_str = format_end (mili second) . format second . format minute . format hour . format day . format_start year
 
 -- |Show a unit with all possible SI-prefixes.
 --
 -- >>> meta_str meter (c |*| 1 *| year)
 -- "9 Pm, 460 Tm, 536 Gm, 207 Mm, 68 km, 16 m"
-meta_str :: (Convertible' a b, Convertible c d, MapEq a c, MapNull (MapMerge (MapTimes POne (MapNeg c)) c)) => Value Rational c (Unit d) -> Value Rational a b -> String
+meta_str :: (Convertible' a b, Convertible c d, MapEq a c, MapNull (MapMerge (MapTimes POne (MapNeg c)) c)) => Value c (U d) Rational -> Value a b Rational -> String
 meta_str unit v = format_end (yocto unit) $ format (zepto unit) $ format (atto unit) $ format (femto unit)
 					$ format (pico unit) $ format (nano unit) $ format (micro unit) $ format (mili unit)
 					$ format unit $ format (kilo unit) $ format (mega unit) $ format (giga unit)
+{-# LANGUAGE KindSignatures, DataKinds, MultiParamTypeClasses, FunctionalDependencies, ExistentialQuantification, TypeFamilies #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE StandaloneDeriving #-}
+
+module Main where
+
+import UnitTyped
+import UnitTyped.SI
+import UnitTyped.SI.Derived
+import UnitTyped.SI.Derived.Length
+import UnitTyped.SI.Derived.Mass
+import UnitTyped.SI.Derived.Count
+import UnitTyped.SI.Derived.Time
+import UnitTyped.SI.Meta
+import UnitTyped.SI.Constants
+import UnitTyped.Bytes
+import UnitTyped.NoPrelude
+import UnitTyped.SI.Show
+
+import qualified Prelude
+import Control.Monad (foldM, unless)
+import Data.Ratio
+import qualified Data.Array.Repa as Repa
+import qualified Data.Array.Repa.Eval as Repa
+import qualified Data.Vector as V
+import qualified Data.Vector.Unboxed as VU
+import Prelude (zip, show, (++), IO, Bool(..), Integer, Double, return, error, putStrLn, fromIntegral)
+import System.Exit (exitFailure)
+
+x1 :: Value LengthDimension (U Meter) Rational
+x1 = 1 *| meter
+
+t1 = x1 == 72 *| centi meter + 280 *| mili meter
+
+
+type DoubleMeter = Value LengthDimension (U Meter) Double
+
+vx2 :: V.Vector (Value LengthDimension (U Meter) Rational)
+vx2 = V.generate 100 (\i -> fromIntegral i *| meter)
+
+vux2d :: VU.Vector DoubleMeter
+vux2d = VU.generate 100 (\i -> fromIntegral i *| meter)
+
+rux2d :: Repa.Array Repa.U Repa.DIM1 DoubleMeter
+rux2d = Repa.fromUnboxed (Repa.ix1 100) vux2d
+
+t2 = (Repa.foldAllS (|+|) (0*| meter) rux2d) Prelude.== 4950 *| meter
+
+deriving instance Repa.Elt f => Repa.Elt (Value a b f)
+
+runTest :: Bool -> (Bool, Integer) -> IO Bool
+runTest b (True, _) = return b
+runTest b (False, i) = do { putStrLn ("Test " ++ show i ++ " failed.")
+                                                  ; return False
+                                                  }
+
+main = do { b <- foldM runTest True (zip [t1, t2] [1..])
+                  ; unless b exitFailure
+                  }
   tag: 0.2
 
 library
-  build-depends:   base >= 4.7 && < 4.8, time, old-locale
+  build-depends:   base >= 4.7 && < 4.8, vector >= 0.10, time, old-locale, containers
   extensions:      FlexibleInstances
                    UndecidableInstances
                    FunctionalDependencies
                    EmptyDataDecls
                    TypeOperators
                    RankNTypes
+                   DeriveDataTypeable
   exposed-modules: UnitTyped
                    UnitTyped.SI
                    UnitTyped.SI.Derived
     type:          exitcode-stdio-1.0
     main-is:       tests/TestSI.hs
     build-depends: base >= 4.7 && < 4.8, unittyped
+