Commits

Thijs Alkemade committed 017b0c8

Implemented value demotion: given necessary Typeable instances, it's possible to extract the unit and the dimension as Map TypeRep Integers.

  • Participants
  • Parent commits 67e785b

Comments (0)

Files changed (13)

File src/UnitTyped.hs

 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE DataKinds #-}
+{-# LANGUAGE InstanceSigs #-}
 
 -- |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,
         (*|), (|*), (|/), (/|), (|+), (+|), (|-), (-|),
         (|==|), (|<=|), (|<|), (|>=|), (|>|),
 
+        dimension, unit,
+
         square, cubic
 ) where
 
 import Data.Foldable
 import Data.Traversable
 
+import qualified Data.Map as M
+import Data.Typeable
+
 -- |Type level natural numbers (excluding zero, though).
 data Nat = One | Suc Nat
 
 instance (FromNumber (Neg a)) => FromNumber (Neg (Suc a)) where
         fromNumber _ = -1 + (fromNumber (undefined :: NumberProxy (Neg a)))
 
+class Dimension a where
+    dimension :: Value a b f -> M.Map TypeRep Integer
+
+instance Dimension '[] where
+    dimension _ = M.empty
+
+instance (Typeable dim, FromNumber value, Dimension rest) => 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)) (fromNumber (error "fromNumber" :: NumberProxy 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, FromNumber value, Unit rest) => 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)) (fromNumber (error "fromNumber" :: NumberProxy 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, POne) ]
+type U a = '[ '(a, POne) ]
 
 -- |Convertible' is a class that models the fact that the composed unit 'b' has dimension 'a'.
 class Convertible' (a :: [(*, Number)]) (b :: [(*, Number)]) where

File 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) ]
+type DataDimension = U Data
 
 -- |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 DataDimension (Unit Byte) f
+byte :: (Fractional f) => Value DataDimension (U Byte) f
 byte = one
 
 -- |One bit.
-bit :: (Fractional f) => Value DataDimension (Unit Bit) f
+bit :: (Fractional f) => Value DataDimension (U Bit) f
 bit = one

File src/UnitTyped/NoPrelude.hs

 -- |Calculate the tangens of a value. Works on 'Degree' and 'Radian'.
 tan = wrap1 Prelude.tan
 
-wrap2 :: (Floating f) => (f -> f) -> Value '[] '[] f -> Value '[] (Unit Radian) f
+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 '[] (Unit Radian) f
+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.

File src/UnitTyped/SI.hs

 -- |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, (Pos One)) ]
 
 
 -- |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, (Pos One)) ]
 
 
 -- |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, (Pos One)) ]
 
 
 -- |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, (Pos One)) ]
 
 
 -- |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, (Pos One)) ]
 
 
 -- |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, (Pos One)) ]
 
 
 -- |The SI unit for 'Luminous' intensity: candela (cd).
 data Candela
+	deriving Typeable
 
 instance Convertible LuminousDimension Candela where
 	factor _ = 1
 --
 
 -- |One meter (m).
-meter :: (Fractional f) => Value LengthDimension (Unit Meter) f
+meter :: (Fractional f) => Value LengthDimension (U Meter) f
 meter = one
 
 --
 
 -- |One second (s).
-second :: (Fractional f) => Value TimeDimension (Unit Second) f
+second :: (Fractional f) => Value TimeDimension (U Second) f
 second = one
 
 --
 
 -- |One gram (g).
-gram :: (Fractional f) => Value MassDimension (Unit Gram) f
+gram :: (Fractional f) => Value MassDimension (U Gram) f
 gram = one
 
 --
 
 -- |One Kelvin (K).
-kelvin :: (Fractional f) => Value TemperatureDimension (Unit Kelvin) f
+kelvin :: (Fractional f) => Value TemperatureDimension (U Kelvin) f
 kelvin = one
 
 --
 
 -- |One ampere (A).
-ampere :: (Fractional f) => Value CurrentDimension (Unit Ampere) f
+ampere :: (Fractional f) => Value CurrentDimension (U Ampere) f
 ampere = one
 
 --
 
 -- |One candela (cd).
-candela :: (Fractional f) => Value LuminousDimension (Unit Candela) f
+candela :: (Fractional f) => Value LuminousDimension (U Candela) f
 candela = one

File src/UnitTyped/SI/Constants.hs

 hbar = coerce (h |/| (2 *| UnitTyped.SI.Constants.pi)) (joule |*| second)
 
 -- |Atomic unit of charge (elementary charge)
-e :: (Fractional f) => Value Charge (Unit Coulomb) f
+e :: (Fractional f) => Value Charge (U Coulomb) f
 e = mkVal 1.6021765314e-19
 
 -- |Atomic unit of mass (electron mass)
-m_e :: (Fractional f) => Value MassDimension (Unit (Kilo Gram)) f
+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 LengthDimension (Unit Meter) f
+a_0 :: (Fractional f) => Value LengthDimension (U Meter) f
 a_0 = mkVal 0.529177210818e-10
 
 -- |Atomic unit of energy
-e_h :: (Fractional f) => Value Energy (Unit Joule) f
+e_h :: (Fractional f) => Value Energy (U Joule) f
 e_h = mkVal 4.3597441775e-18
 
 -- |Gas constant.
 g = mkVal 6.6738480e-11
 
 ---- |Planck mass
---m_P :: (Fractional f, Floating f) => Value f MassDimension (Unit (Kilo Gram))
+--m_P :: (Fractional f, Floating f) => Value f MassDimension (U (Kilo Gram))
 --m_P = mkVal (sqrt (val $ hbar |*| c |/| g))
 
 ---- |Reduced Planck mass
---m_P' :: (Fractional f, Floating f) => Value f MassDimension (Unit (Kilo Gram))
+--m_P' :: (Fractional f, Floating f) => Value f MassDimension (U (Kilo Gram))
 --m_P' = mkVal (sqrt (val $ hbar |*| c |/| ((Prelude.pi * 8) *| g)))

File 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 Speed (Unit Knot) f
+knot :: (Fractional f) => Value Speed (U Knot) f
 knot = one
 
 -- |One newton.
-newton :: (Fractional f) => Value '[ '(Time, NTwo), '(Mass, POne), '(Length, POne)] (Unit Newton) f
+newton :: (Fractional f) => Value '[ '(Time, NTwo), '(Mass, POne), '(Length, POne)] (U Newton) f
 newton = one
 
 -- |One joule.
-joule :: (Fractional f) => Value Energy (Unit Joule) f
+joule :: (Fractional f) => Value Energy (U Joule) f
 joule = one
 
 -- |One eV.
-eV :: (Fractional f) => Value Energy (Unit Ev) f
+eV :: (Fractional f) => Value Energy (U Ev) f
 eV = one
 
 -- |One kwh.
 kwh = one
 
 -- |One watt.
-watt :: (Fractional f) => Value Power (Unit Watt) f
+watt :: (Fractional f) => Value Power (U Watt) f
 watt = one
 
 -- |One pascal.
-pascal :: (Fractional f) => Value Pressure (Unit Pascal) f
+pascal :: (Fractional f) => Value Pressure (U Pascal) f
 pascal = one
 
 -- |One bar.
-bar :: (Fractional f) => Value Pressure (Unit Bar) f
+bar :: (Fractional f) => Value Pressure (U Bar) f
 bar = one
 
 -- |One mmHg.
-mmHg :: (Fractional f) => Value Pressure (Unit MmHg) f
+mmHg :: (Fractional f) => Value Pressure (U MmHg) f
 mmHg = one
 
 -- |One coulomb.
-coulomb :: (Fractional f) => Value Charge (Unit Coulomb) f
+coulomb :: (Fractional f) => Value Charge (U Coulomb) f
 coulomb = one
 
 -- |One volt.
-volt :: (Fractional f) => Value Potential (Unit Volt) f
+volt :: (Fractional f) => Value Potential (U Volt) f
 volt = one
 
 -- |One farad.
-farad :: (Fractional f) => Value Capacitance (Unit Farad) f
+farad :: (Fractional f) => Value Capacitance (U Farad) f
 farad = one
 
 -- |One ohm.
-ohm :: (Fractional f) => Value Resistance (Unit Ohm) f
+ohm :: (Fractional f) => Value Resistance (U Ohm) f
 ohm = one
 
 -- |One siemens.
-siemens :: (Fractional f) => Value Conductance (Unit Siemens) f
+siemens :: (Fractional f) => Value Conductance (U Siemens) f
 siemens = one
 
 -- |One weber.
-weber :: (Fractional f) => Value Flux (Unit Weber) f
+weber :: (Fractional f) => Value Flux (U Weber) f
 weber = one
 
 -- |One tesla.
-tesla :: (Fractional f) => Value FluxDensity (Unit Tesla) f
+tesla :: (Fractional f) => Value FluxDensity (U Tesla) f
 tesla = one
 
 -- |One henry.
-henry :: (Fractional f) => Value Inductance (Unit Henry) f
+henry :: (Fractional f) => Value Inductance (U Henry) f
 henry = one

File 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 '[] (Unit Percentage) f
+percent :: (Fractional f) => Value '[] (U Percentage) f
 percent = one
 
 -- |One per mille (‰).
-permil :: (Fractional f) => Value '[] (Unit Permil) f
+permil :: (Fractional f) => Value '[] (U Permil) f
 permil = one
 
 -- |One part per million (ppm).
-ppm :: (Fractional f) => Value '[] (Unit Ppm) f
+ppm :: (Fractional f) => Value '[] (U Ppm) f
 ppm = one
 
 -- |One part per billion (ppb).
-ppb :: (Fractional f) => Value '[] (Unit Ppb) f
+ppb :: (Fractional f) => Value '[] (U Ppb) f
 ppb = one
 
 -- |One part per trillion (ppt).
-ppt :: (Fractional f) => Value '[] (Unit Ppt) f
+ppt :: (Fractional f) => Value '[] (U Ppt) f
 ppt = one
 
 -- |One rad (rad).
-rad :: (Fractional f) => Value '[] (Unit Radian) f
+rad :: (Fractional f) => Value '[] (U Radian) f
 rad = one
 
 -- |One degree (˚).
-deg :: (Fractional f) => Value '[] (Unit Degree) f
+deg :: (Fractional f) => Value '[] (U Degree) f
 deg = one

File 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 LengthDimension (Unit Mile) f
+mile :: (Fractional f) => Value LengthDimension (U Mile) f
 mile = one
 
 -- |One inch (in).
-inch :: (Fractional f) => Value LengthDimension (Unit Inch) f
+inch :: (Fractional f) => Value LengthDimension (U Inch) f
 inch = one
 
 -- |One yard (yd).
-yard :: (Fractional f) => Value LengthDimension (Unit Yard) f
+yard :: (Fractional f) => Value LengthDimension (U Yard) f
 yard = one
 
 -- |One foot (ft).
-foot :: (Fractional f) => Value LengthDimension (Unit Foot) f
+foot :: (Fractional f) => Value LengthDimension (U Foot) f
 foot = one
 
-ångström, angstrom :: (Fractional f) => Value LengthDimension (Unit Ångström) f
+å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 LengthDimension (Unit NauticalMile) f
+nautical_mile :: (Fractional f) => Value LengthDimension (U NauticalMile) f
 nautical_mile = one
 
 --
 
 -- |One barn (b).
-barn :: (Fractional f) => Value AreaUnit (Unit Barn) f
+barn :: (Fractional f) => Value AreaUnit (U Barn) f
 barn = one
 
 --
 
 -- |One liter (L).
-liter :: (Fractional f) => Value VolumeUnit (Unit Liter) f
+liter :: (Fractional f) => Value VolumeUnit (U Liter) f
 liter = one
 
 -- |One gallon (gallon).
-gallon :: (Fractional f) => Value VolumeUnit (Unit Gallon) f
+gallon :: (Fractional f) => Value VolumeUnit (U Gallon) f
 gallon = one
 
 -- |One fluid ounce (fl oz).
-fluid_ounce :: (Fractional f) => Value VolumeUnit (Unit FluidOunce) f
+fluid_ounce :: (Fractional f) => Value VolumeUnit (U FluidOunce) f
 fluid_ounce = one

File 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 MassDimension (Unit Pound) f
+pound :: (Fractional f) => Value MassDimension (U Pound) f
 pound = one

File 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, Neg One) ] Hertz where
 	factor _ = 1
 --
 
 -- |One minute (min.).
-minute :: (Fractional f) => Value TimeDimension (Unit Minute) f
+minute :: (Fractional f) => Value TimeDimension (U Minute) f
 minute = one
 
 -- |One hour (h).
-hour :: (Fractional f) => Value TimeDimension (Unit Hour) f
+hour :: (Fractional f) => Value TimeDimension (U Hour) f
 hour = one
 
 -- |One day (day).
-day :: (Fractional f) => Value TimeDimension (Unit Day) f
+day :: (Fractional f) => Value TimeDimension (U Day) f
 day = one
 
 -- |One year (yr).
-year :: (Fractional f) => Value TimeDimension (Unit Year) f
+year :: (Fractional f) => Value TimeDimension (U Year) f
 year = one
 
 -- |One Julian year (a).
-julian_year :: (Fractional f) => Value TimeDimension (Unit JulianYear) f
+julian_year :: (Fractional f) => Value TimeDimension (U JulianYear) f
 julian_year = one
 
 -- |One month (month).
-month :: (Fractional f) => Value TimeDimension (Unit Month) f
+month :: (Fractional f) => Value TimeDimension (U Month) f
 month = one
 
 -- |One herz (Hz).
-hertz :: (Fractional f) => Value '[ '(Time, NOne) ] (Unit Hertz) f
+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 TimeDimension (Unit Second) f
+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 TimeDimension (Unit Second) f
+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 TimeDimension (Unit Second) f)
+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 TimeDimension (Unit Second) f)
+since_str :: (Fractional f) => String -> String -> IO (Value TimeDimension (U Second) f)
 since_str fmt str = since (DTF.readTime SL.defaultTimeLocale fmt str)

File 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 a (Unit b) f -> Value a (Unit (Deca b)) f
+deca :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Deca b)) f
 deca (Value x) = (Value x)
 
 -- |Take a unit and return one hecto(unit).
-hecto :: (Convertible a b, Fractional f) => Value a (Unit b) f -> Value a (Unit (Hecto b)) f
+hecto :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Hecto b)) f
 hecto (Value x) = (Value x)
 
 -- |Take a unit and return one kilo(unit).
-kilo :: (Convertible a b, Fractional f) => Value a (Unit b) f -> Value a (Unit (Kilo b)) f
+kilo :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Kilo b)) f
 kilo (Value x) = (Value x)
 
 -- |Take a unit and return one mega(unit).
-mega :: (Convertible a b, Fractional f) => Value a (Unit b) f -> Value a (Unit (Mega b)) f
+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 a (Unit b) f -> Value a (Unit (Giga b)) f
+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 a (Unit b) f -> Value a (Unit (Tera b)) f
+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 a (Unit b) f -> Value a (Unit (Peta b)) f
+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 a (Unit b) f -> Value a (Unit (Exa b)) f
+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 a (Unit b) f -> Value a (Unit (Zetta b)) f
+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 a (Unit b) f -> Value a (Unit (Yotta b)) f
+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 a (Unit b) f -> Value a (Unit (Deci b)) f
+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 a (Unit b) f -> Value a (Unit (Centi b)) f
+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 a (Unit b) f -> Value a (Unit (Mili b)) f
+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 a (Unit b) f -> Value a (Unit (Micro b)) f
+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 a (Unit b) f -> Value a (Unit (Nano b)) f
+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 a (Unit b) f -> Value a (Unit (Pico b)) f
+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 a (Unit b) f -> Value a (Unit (Femto b)) f
+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 a (Unit b) f -> Value a (Unit (Atto b)) f
+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 a (Unit b) f -> Value a (Unit (Zepto b)) f
+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 a (Unit b) f -> Value a (Unit (Yocto b)) f
+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 a (Unit b) f -> Value a (Unit (Kibi b)) f
+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 a (Unit b) f -> Value a (Unit (Mebi b)) f
+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 a (Unit b) f -> Value a (Unit (Gibi b)) f
+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 a (Unit b) f -> Value a (Unit (Tebi b)) f
+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 a (Unit b) f -> Value a (Unit (Pebi b)) f
+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 a (Unit b) f -> Value a (Unit (Exbi b)) f
+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 a (Unit b) f -> Value a (Unit (Zebi b)) f
+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 a (Unit b) f -> Value a (Unit (Yobi b)) f
+yobi :: (Convertible a b, Fractional f) => Value a (U b) f -> Value a (U (Yobi b)) f
 yobi (Value x) = (Value x)

File src/UnitTyped/SI/Show.hs

 --
 -- >>> 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 'True) => Value c (Unit d) Rational -> Value a b Rational -> String
+meta_str :: (Convertible' a b, Convertible c d, MapEq a c 'True) => 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)

File unittyped.cabal

   tag: 0.2
 
 library
-  build-depends:   base >= 4.6 && < 4.7, time, old-locale
+  build-depends:   base >= 4.6 && < 4.7, time, old-locale, containers
   extensions:      FlexibleInstances
                    UndecidableInstances
                    FunctionalDependencies
                    EmptyDataDecls
                    TypeOperators
                    RankNTypes
+                   DeriveDataTypeable
   exposed-modules: UnitTyped
                    UnitTyped.SI
                    UnitTyped.SI.Derived