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 |
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)