| Copyright | (C) 2014 Richard Eisenberg |
|---|---|
| License | BSD-style (see LICENSE) |
| Maintainer | Richard Eisenberg (rae@cs.brynmawr.edu) |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | None |
| Language | Haskell2010 |
Data.Metrology.TH
Description
This module exports Template Haskell functions to make working with
units a little more convenient.
Synopsis
- evalType :: Q Type -> Q Type
- declareDimension :: String -> Q [Dec]
- declareCanonicalUnit :: String -> Q Type -> Maybe String -> Q [Dec]
- declareDerivedUnit :: String -> Q Type -> Rational -> Maybe String -> Q [Dec]
- declareMonoUnit :: String -> Maybe String -> Q [Dec]
- declareConstant :: String -> Rational -> Q Type -> Q [Dec]
Documentation
evalType :: Q Type -> Q Type Source #
Evaluates a type as far as it can. This is useful, say, in instance declarations:
instance Show $(evalType [t| Length |]) where ...
Without the evalType, the instance declaration fails because Length
mentions type families, which can't be used in instance declarations.
This function is somewhat experimental, and will likely not work with more polymorphic types. (If it doesn't work, not all of the type families will be evaluated, and the instance declaration will fail. This function should never cause incorrect behavior.)
declareDimension :: String -> Q [Dec] Source #
Declare a new dimension of the given name:
$(declareDimension "Length")
produces
data Length = Length instance Dimension Length
declareCanonicalUnit :: String -> Q Type -> Maybe String -> Q [Dec] Source #
declareCanonicalUnit unit_name dim (Just abbrev) creates a new
canonical unit (that is, it is not defined in terms of other known units)
named unit_name, measuring dimension dim. abbrev will be the
abbreviation in the unit's Show instance. If no abbraviation is supplied,
then no Show instance will be generated.
Example usage:
$(declareCanonicalUnit "Meter" [t| Length |] (Just "m"))
declareDerivedUnit :: String -> Q Type -> Rational -> Maybe String -> Q [Dec] Source #
declareDerivedUnit unit_name base_unit_type ratio (Just abbrev) creates
a new derived unit, expressed in terms of base_unit_type. ratio says
how many base units are in the derived unit. (Thus, if unit_name is
Minute and base_unit_type is ''Second, then ratio would be 60.)
abbrev, if supplied, becomes the string produced in the derived unit's
Show instance. If no abbreviation is supplied, no Show instance is
generated.
Example usage:
$(declareDerivedUnit "Minute" [t| Second |] 60 (Just "min"))
declareMonoUnit :: String -> Maybe String -> Q [Dec] Source #
declareMonoUnit unit_name (Just abbrev) creates a new derived unit,
intended for use without unit polymorphism. The same type stands for both
the unit and dimension, and the instance of DefaultUnitOfDim is set up
accordingly. Use this function (with the Metrology imports) if you
don't want to bother with LCSUs and just want to get to work. The abbrev,
if supplied, creates an appropriate Show instance.
$(declareMonoUnit "Meter" (Just "m"))
produces all of the following
data Meter = Meter instance Dimension Meter instance Unit Meter where type BaseUnit Meter = Canonical type DimOfUnit Meter = Meter type instance DefaultUnitOfDim Meter = Meter instance Show Meter where show _ = "m"
After a declaration like this, you probably want
type Length = MkQu_U Meter
This last line is not generated, as it is easy enough for you to write,
and it involves a new name (Length).
declareConstant :: String -> Rational -> Q Type -> Q [Dec] Source #
declareConstant const_name value unit_type creates a new numerical
constant, named const_name. Its numerical value is value expressed
in units given by unit_type. The constant is polymorphic in both its
LCSU and numerical representation. For example,
declareConstant "gravity_g" 9.80665 [t| Meter :/ Second :^ Two |]
yields
gravity_g :: forall lcsu n.
( Fractional n
, CompatibleUnit lcsu (Meter :/ Second :^ Two) )
=> MkQu_ULN (Meter :/ Second :^ Two) lcsu n
gravity_g = 9.80665 % (undefined :: Meter :/ Second :^ Two)