-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A domain-specific type system for dimensional analysis -- @package units @version 2.2.1 -- | This module defines a datatype and operations to represent type-level -- integers. Though it's defined as part of the units package, it may be -- useful beyond dimensional analysis. If you have a compelling non-units -- use of this package, please let me (Richard, eir at -- cis.upenn.edu) know. module Data.Metrology.Z -- | The datatype for type-level integers. data Z Zero :: Z S :: Z -> Z P :: Z -> Z -- | The singleton kind-indexed data family. type SZ (z_a9V4 :: Z) = Sing z_a9V4 type ZeroSym0 = Zero data SSym0 (l_a9UZ :: TyFun Z Z) type SSym1 (t_a9UY :: Z) = S t_a9UY data PSym0 (l_a9V2 :: TyFun Z Z) type PSym1 (t_a9V1 :: Z) = P t_a9V1 -- | Convert a Z to an Int zToInt :: Z -> Int -- | Convert a singleton Z to an Int. szToInt :: Sing (z :: Z) -> Int -- | Add one to an integer -- | Subtract one from an integer -- | Negate an integer -- | Add two integers -- | Subtract two integers -- | Multiply two integers -- | Divide two integers -- | Add one to a singleton Z. sSucc :: Sing z -> Sing (Succ z) -- | Subtract one from a singleton Z. sPred :: Sing z -> Sing (Pred z) -- | Negate a singleton Z. sNegate :: Sing z -> Sing (Negate z) -- | Less-than comparison -- | Check if a type-level integer is in fact a natural number type One = S Zero type Two = S One type Three = S Two type Four = S Three type Five = S Four type MOne = P Zero type MTwo = P MOne type MThree = P MTwo type MFour = P MThree type MFive = P MFour -- | This is the singleton value representing Zero at the term -- level and at the type level, simultaneously. Used for raising units to -- powers. sZero :: Sing Z Zero sOne :: Sing Z (S Zero) sTwo :: Sing Z (S (S Zero)) sThree :: Sing Z (S (S (S Zero))) sFour :: Sing Z (S (S (S (S Zero)))) sFive :: Sing Z (S (S (S (S (S Zero))))) sMOne :: Sing Z (P Zero) sMTwo :: Sing Z (P (P Zero)) sMThree :: Sing Z (P (P (P Zero))) sMFour :: Sing Z (P (P (P (P Zero)))) sMFive :: Sing Z (P (P (P (P (P Zero))))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pZero :: Sing Z Zero -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pOne :: Sing Z (S Zero) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pTwo :: Sing Z (S (S Zero)) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pThree :: Sing Z (S (S (S Zero))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pFour :: Sing Z (S (S (S (S Zero)))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pFive :: Sing Z (S (S (S (S (S Zero))))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pMOne :: Sing Z (P Zero) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pMTwo :: Sing Z (P (P Zero)) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pMThree :: Sing Z (P (P (P Zero))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pMFour :: Sing Z (P (P (P (P Zero)))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pMFive :: Sing Z (P (P (P (P (P Zero))))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pSucc :: Sing Z z -> Sing Z (Succ z) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pPred :: Sing Z z -> Sing Z (Pred z) instance Eq Z instance SingI n0 => SingI ('P n0) instance SingI n0 => SingI ('S n0) instance SingI 'Zero instance SDecide 'KProxy instance SEq 'KProxy instance SingKind 'KProxy instance SuppressUnusedWarnings PSym0 instance SuppressUnusedWarnings SSym0 instance PEq 'KProxy -- | This module defines a few set-like operations on type-level lists. It -- may be applicable beyond the units package. module Data.Metrology.Set -- | Are two lists equal, when considered as sets? -- | Is one list a subset of the other? -- | Is an element contained in a list? -- | This module defines Show instance for quantities. The show -- instance prints out the number stored internally with its correct -- units. To print out quantities with specific units use the function -- showIn. module Data.Metrology.Show instance (ShowUnitFactor (LookupList dims lcsu), Show n) => Show (Qu dims lcsu n) instance (ShowUnitFactor rest, Show unit, SingI z) => ShowUnitFactor ('F unit z : rest) instance ShowUnitFactor '[] -- | This module exports the constructor of the Qu type. This allows -- you to write code that takes creates and reads quantities at will, -- which may lead to dimension unsafety. Use at your peril. module Data.Metrology.Unsafe -- | Qu adds a dimensional annotation to its numerical value type -- n. This is the representation for all quantities. newtype Qu (a :: [Factor *]) (lcsu :: LCSU *) (n :: *) Qu :: n -> Qu -- | This file gathers and exports user-visible type-level definitions, to -- make error messages less cluttered. Non-expert users should never have -- to use the definitions exported from this module. module Data.Metrology.Internal -- | Are two LCSUs inter-convertible at the given dimension? -- | Check if a (dimension factors, LCSU, unit) triple are all valid to be -- used together. -- | Check if a (dimension factors, LCSU) pair are valid to be used -- together. This checks that each dimension maps to a unit of the -- correct dimension. -- | Check if two [Factor *]s, representing units, should -- be considered to be equal -- | Given a list of unit factors, extract out the canonical units they are -- based on. -- | Check to make sure that a unit has the same dimension as its base -- unit, if any. -- | Is this unit a canonical unit? -- | Get the canonical unit from a given unit. For example: -- CanonicalUnit Foot = Meter type CanonicalUnit (unit :: *) = CanonicalUnit' (BaseUnit unit) unit -- | Helper function in CanonicalUnit -- | Essentially, a constraint that checks if a conversion ratio can be -- calculated for a BaseUnit of a unit. -- | Classifies well-formed list of unit factors, and permits calculating a -- conversion ratio for the purposes of LCSU conversions. class UnitFactor (units :: [Factor *]) -- | This will only be used at the kind level. It holds a dimension or unit -- with its exponent. data Factor star F :: star -> Z -> Factor star -- | Do these Factors represent the same dimension? -- | (Extract s lst) pulls the Factor that matches s out of lst, -- returning a diminished list and, possibly, the extracted Factor. -- --
--   Extract A [A, B, C] ==> ([B, C], Just A
--   Extract F [A, B, C] ==> ([A, B, C], Nothing)
--   
-- | Reorders a to be the in the same order as b, putting entries not in b -- at the end -- --
--   Reorder [A 1, B 2] [B 5, A 2] ==> [B 2, A 1]
--   Reorder [A 1, B 2, C 3] [C 2, A 8] ==> [C 3, A 1, B 2]
--   Reorder [A 1, B 2] [B 4, C 1, A 9] ==> [B 2, A 1]
--   Reorder x x ==> x
--   Reorder x [] ==> x
--   Reorder [] x ==> []
--   
-- | Helper function in Reorder -- | Check if two [Factor *]s should be considered to be equal -- | Take a [Factor *] and remove any Factors with an -- exponent of 0 -- | Adds corresponding exponents in two dimension, assuming the lists are -- ordered similarly. -- | Adds corresponding exponents in two dimension, preserving order -- | Subtract exponents in two dimensions, assuming the lists are ordered -- similarly. -- | Subtract exponents in two dimensions -- | negate a single Factor -- | negate a list of Factors -- | Multiplication of the exponents in a dimension by a scalar -- | Division of the exponents in a dimension by a scalar -- | Exports combinators for building quantities out of vectors, from the -- vector-space library. module Data.Metrology.Vector -- | The number 0, polymorphic in its dimension. Use of this will often -- require a type annotation. zero :: AdditiveGroup n => Qu dimspec l n -- | Add two compatible quantities (|+|) :: (d1 @~ d2, AdditiveGroup n) => Qu d1 l n -> Qu d2 l n -> Qu d1 l n -- | Subtract two compatible quantities (|-|) :: (d1 @~ d2, AdditiveGroup n) => Qu d1 l n -> Qu d2 l n -> Qu d1 l n -- | Take the sum of a list of quantities qSum :: (Foldable f, AdditiveGroup n) => f (Qu d l n) -> Qu d l n -- | Negate a quantity qNegate :: AdditiveGroup n => Qu d l n -> Qu d l n -- | Multiply two quantities (|*|) :: Num n => Qu a l n -> Qu b l n -> Qu (Normalize (a @+ b)) l n -- | Divide two quantities (|/|) :: Fractional n => Qu a l n -> Qu b l n -> Qu (Normalize (a @- b)) l n -- | Divide a scalar by a quantity (/|) :: Fractional n => n -> Qu b l n -> Qu (Normalize ([] @- b)) l n -- | Multiply a quantity by a scalar from the left (*|) :: VectorSpace n => Scalar n -> Qu b l n -> Qu b l n -- | Multiply a quantity by a scalar from the right (|*) :: VectorSpace n => Qu a l n -> Scalar n -> Qu a l n -- | Divide a quantity by a scalar (|/) :: (VectorSpace n, Fractional (Scalar n)) => Qu a l n -> Scalar n -> Qu a l n -- | Multiply a scalar quantity by a vector quantity (|*^|) :: VectorSpace n => Qu d1 l (Scalar n) -> Qu d2 l n -> Qu (Normalize (d1 @+ d2)) l n -- | Multiply a vector quantity by a scalar quantity (|^*|) :: VectorSpace n => Qu d1 l n -> Qu d2 l (Scalar n) -> Qu (Normalize (d1 @+ d2)) l n -- | Divide a vector quantity by a scalar quantity (|^/|) :: (VectorSpace n, Fractional (Scalar n)) => Qu d1 l n -> Qu d2 l (Scalar n) -> Qu (Normalize (d1 @- d2)) l n -- | Take a inner (dot) product between two quantities. (|.|) :: InnerSpace n => Qu d1 l n -> Qu d2 l n -> Qu (Normalize (d1 @+ d2)) l (Scalar n) -- | Raise a quantity to a integer power, knowing at compile time that the -- integer is non-negative. (|^) :: (NonNegative z, Num n) => Qu a l n -> Sing z -> Qu (a @* z) l n -- | Raise a quantity to a integer power known at compile time (|^^) :: Fractional n => Qu a l n -> Sing z -> Qu (a @* z) l n -- | Take the n'th root of a quantity, where n is known at compile time qNthRoot :: ((Zero < z) ~ True, Floating n) => Sing z -> Qu a l n -> Qu (a @/ z) l n -- | Square a quantity qSq :: Num n => Qu a l n -> Qu (Normalize (a @+ a)) l n -- | Cube a quantity qCube :: Num n => Qu a l n -> Qu (Normalize (Normalize (a @+ a) @+ a)) l n -- | Take the square root of a quantity qSqrt :: Floating n => Qu a l n -> Qu (a @/ Two) l n -- | Take the cubic root of a quantity qCubeRoot :: Floating n => Qu a l n -> Qu (a @/ Three) l n -- | Square the length of a vector. qMagnitudeSq :: InnerSpace n => Qu d l n -> Qu (d @* Two) l (Scalar n) -- | Length of a vector. qMagnitude :: (InnerSpace n, Floating (Scalar n)) => Qu d l n -> Qu d l (Scalar n) -- | Vector in same direction as given one but with length of one. If given -- the zero vector, then return it. The returned vector is dimensionless. qNormalized :: (InnerSpace n, Floating (Scalar n)) => Qu d l n -> Qu [] l n -- | qProject u v computes the projection of v onto -- u. qProject :: (InnerSpace n, Floating (Scalar n)) => Qu d2 l n -> Qu d1 l n -> Qu d1 l n -- | Cross product of 2D vectors. qCross2 :: HasCross2 n => Qu d l n -> Qu d l n -- | Cross product of 3D vectors. qCross3 :: HasCross3 n => Qu d1 l n -> Qu d2 l n -> Qu (Normalize (d1 @+ d2)) l n -- | A Point n is an affine space built over n. Two -- Points cannot be added, but they can be subtracted to yield a -- difference of type n. newtype Point n Point :: n -> Point n -- | Make a point quantity from a non-point quantity. -- | Subtract point quantities. (|.-.|) :: (d1 @~ d2, AffineSpace n) => Qu d1 l n -> Qu d2 l n -> Qu d1 l (Diff n) -- | Add a point to a vector. (|.+^|) :: (d1 @~ d2, AffineSpace n) => Qu d1 l n -> Qu d2 l (Diff n) -> Qu d1 l n -- | Subract a vector from a point. (|.-^|) :: (d1 @~ d2, AffineSpace n) => Qu d1 l n -> Qu d2 l (Diff n) -> Qu d1 l n -- | Square of the distance between two points. qDistanceSq :: (d1 @~ d2, AffineSpace n, InnerSpace (Diff n)) => Qu d1 l n -> Qu d2 l n -> Qu (d1 @* Two) l (Scalar (Diff n)) -- | Distance between two points. qDistance :: (d1 @~ d2, AffineSpace n, InnerSpace (Diff n), Floating (Scalar (Diff n))) => Qu d1 l n -> Qu d2 l n -> Qu d1 l (Scalar (Diff n)) -- | Compare two quantities qCompare :: (d1 @~ d2, Ord n) => Qu d1 l n -> Qu d2 l n -> Ordering -- | Check if one quantity is less than a compatible one (|<|) :: (d1 @~ d2, Ord n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Check if one quantity is greater than a compatible one (|>|) :: (d1 @~ d2, Ord n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Check if one quantity is less than or equal to a compatible one (|<=|) :: (d1 @~ d2, Ord n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Check if one quantity is greater than or equal to a compatible one (|>=|) :: (d1 @~ d2, Ord n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Check if two quantities are equal (uses the equality of the underlying -- numerical type) (|==|) :: (d1 @~ d2, Eq n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Check if two quantities are not equal (|/=|) :: (d1 @~ d2, Eq n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Compare two compatible quantities for approximate equality. If the -- difference between the left hand side and the right hand side -- arguments are less than or equal to the epsilon, they are -- considered equal. qApprox :: (d0 @~ d1, d0 @~ d2, Num n, Ord n) => Qu d0 l n -> Qu d1 l n -> Qu d2 l n -> Bool -- | Compare two compatible quantities for approixmate inequality. -- qNapprox e a b = not $ qApprox e a b qNapprox :: (d0 @~ d1, d0 @~ d2, Num n, Ord n) => Qu d0 l n -> Qu d1 l n -> Qu d2 l n -> Bool -- | Extracts a numerical value from a dimensioned quantity, expressed in -- the given unit. For example: -- --
--   inMeters :: Length -> Double
--   inMeters x = numIn x Meter
--   
-- -- or -- --
--   inMeters x = x # Meter   
--   
numIn :: (ValidDLU dim lcsu unit, VectorSpace n, Fractional (Scalar n)) => Qu dim lcsu n -> unit -> n -- | Infix synonym for numIn (#) :: (ValidDLU dim lcsu unit, VectorSpace n, Fractional (Scalar n)) => Qu dim lcsu n -> unit -> n -- | Creates a dimensioned quantity in the given unit. For example: -- --
--   height :: Length
--   height = quOf 2.0 Meter
--   
-- -- or -- --
--   height = 2.0 % Meter
--   
quOf :: (ValidDLU dim lcsu unit, VectorSpace n, Fractional (Scalar n)) => n -> unit -> Qu dim lcsu n -- | Infix synonym for quOf (%) :: (ValidDLU dim lcsu unit, VectorSpace n, Fractional (Scalar n)) => n -> unit -> Qu dim lcsu n -- | Show a dimensioned quantity in a given unit. (The default -- Show instance always uses units as specified in the LCSU.) showIn :: (ValidDLU dim lcsu unit, VectorSpace n, Fractional (Scalar n), Show unit, Show n) => Qu dim lcsu n -> unit -> String -- | The number 1, expressed as a unitless dimensioned quantity. unity :: Num n => Qu [] l n -- | Cast between equivalent dimension within the same CSU. for example [kg -- m s] and [s m kg]. See the README for more info. redim :: d @~ e => Qu d l n -> Qu e l n -- | Dimension-keeping cast between different CSUs. convert :: (ConvertibleLCSUs d l1 l2, VectorSpace n, Fractional (Scalar n)) => Qu d l1 n -> Qu d l2 n -- | Use this to choose a default LCSU for a dimensioned quantity. The -- default LCSU uses the DefaultUnitOfDim representation for each -- dimension. defaultLCSU :: Qu dim DefaultLCSU n -> Qu dim DefaultLCSU n -- | Compute the argument in the DefaultLCSU, and present the -- result as lcsu-polymorphic dimension-polymorphic value. Named -- constant because one of its dominant usecase is to inject -- constant quantities into dimension-polymorphic expressions. constant :: (d @~ e, ConvertibleLCSUs e DefaultLCSU l, VectorSpace n, Fractional (Scalar n)) => Qu d DefaultLCSU n -> Qu e l n -- | Multiply two units to get another unit. For example: type -- MetersSquared = Meter :* Meter data (:*) u1 u2 (:*) :: u1 -> u2 -> (:*) u1 u2 -- | Divide two units to get another unit data (:/) u1 u2 (:/) :: u1 -> u2 -> (:/) u1 u2 -- | Raise a unit to a power, known at compile time data (:^) unit (power :: Z) (:^) :: unit -> Sing power -> (:^) unit -- | Multiply a conversion ratio by some constant. Used for defining -- prefixes. data (:@) prefix unit (:@) :: prefix -> unit -> (:@) prefix unit -- | A class for user-defined prefixes class UnitPrefix prefix multiplier :: (UnitPrefix prefix, Fractional f) => prefix -> f -- | Multiply two quantity types to produce a new one. For example: -- --
--   type Velocity = Length %/ Time
--   
-- | Divide two quantity types to produce a new one -- | Exponentiate a quantity type to an integer -- | Qu adds a dimensional annotation to its numerical value type -- n. This is the representation for all quantities. data Qu (a :: [Factor *]) (lcsu :: LCSU *) (n :: *) -- | Make a quantity type capable of storing a value of a given unit. This -- uses a Double for storage of the value. For example: -- --
--   data LengthDim = LengthDim
--   instance Dimension LengthDim
--   data Meter = Meter
--   instance Unit Meter where
--     type BaseUnit Meter = Canonical
--     type DimOfUnit Meter = LengthDim
--   type instance DefaultUnitOfDim LengthDim = Meter
--   type Length = MkQu_D LengthDim
--   
-- -- Note that the dimension must have an instance for the type -- family DefaultUnitOfDim for this to work. type MkQu_D dim = Qu (DimFactorsOf dim) DefaultLCSU Double -- | Make a quantity type with a custom numerical type and LCSU. type MkQu_DLN dim = Qu (DimFactorsOf dim) -- | Make a quantity type with a given unit. It will be stored as a -- Double. Note that the corresponding dimension must have -- an appropriate instance for DefaultUnitOfDim for this to work. type MkQu_U unit = Qu (DimFactorsOf (DimOfUnit unit)) DefaultLCSU Double -- | Make a quantity type with a unit and LCSU with custom numerical type. -- The quantity will have the dimension corresponding to the unit. type MkQu_ULN unit = Qu (DimFactorsOf (DimOfUnit unit)) -- | This class is used to mark abstract dimensions, such as -- Length, or Mass. class Dimension dim where type family DimFactorsOf dim :: [Factor *] type instance DimFactorsOf dim = '[F dim One] class DimOfUnitIsConsistent unit => Unit unit where type family BaseUnit unit :: * type family DimOfUnit unit :: * type family UnitFactorsOf unit :: [Factor *] type instance DimOfUnit unit = DimOfUnit (BaseUnit unit) type instance UnitFactorsOf unit = If (IsCanonical unit) '[F unit One] (UnitFactorsOf (BaseUnit unit)) conversionRatio _ = 1 canonicalConvRatio u = conversionRatio u * baseUnitRatio u conversionRatio :: Unit unit => unit -> Rational -- | Dummy type use just to label canonical units. It does not have -- a Unit instance. data Canonical -- | The dimension for the dimensionless quantities. It is also called -- "quantities of dimension one", but One is confusing with the -- type-level integer One. data Dimensionless Dimensionless :: Dimensionless -- | The unit for unitless dimensioned quantities data Number Number :: Number -- | The type of unitless dimensioned quantities. This is an instance of -- Num, though Haddock doesn't show it. This is parameterized by -- an LCSU and a number representation. type Count = MkQu_ULN Number -- | Convert a raw number into a unitless dimensioned quantity quantity :: n -> Qu [] l n -- | Make a local consistent set of units. The argument is a type-level -- list of tuple types, to be interpreted as an association list from -- dimensions to units. For example: -- --
--   type MyLCSU = MkLCSU '[(Length, Foot), (Mass, Gram), (Time, Year)]
--   
data LCSU star DefaultLCSU :: LCSU star -- | Assign a default unit for a dimension. Necessary only when using -- default LCSUs. -- | Check if an LCSU has consistent entries for the given unit. i.e. can -- the lcsu describe the unit? -- | Check if an LCSU can express the given dimension -- | Like ConvertibleLCSUs, but takes a dimension, not a dimension -- factors. -- | Check if the DefaultLCSU can convert into the given one, at the -- given dimension. -- | Check if the DefaultLCSU can convert into the given one, at the -- given unit. -- | Extract a dimension specifier from a list of factors -- | Extract a unit specifier from a list of factors -- | Extract a unit from a dimension factor list and an LCSU -- | The datatype for type-level integers. data Z Zero :: Z S :: Z -> Z P :: Z -> Z -- | Add one to an integer -- | Subtract one from an integer -- | Add two integers -- | Subtract two integers -- | Multiply two integers -- | Divide two integers -- | Negate an integer type One = S Zero type Two = S One type Three = S Two type Four = S Three type Five = S Four type MOne = P Zero type MTwo = P MOne type MThree = P MTwo type MFour = P MThree type MFive = P MFour -- | This is the singleton value representing Zero at the term -- level and at the type level, simultaneously. Used for raising units to -- powers. sZero :: Sing Z Zero sOne :: Sing Z (S Zero) sTwo :: Sing Z (S (S Zero)) sThree :: Sing Z (S (S (S Zero))) sFour :: Sing Z (S (S (S (S Zero)))) sFive :: Sing Z (S (S (S (S (S Zero))))) sMOne :: Sing Z (P Zero) sMTwo :: Sing Z (P (P Zero)) sMThree :: Sing Z (P (P (P Zero))) sMFour :: Sing Z (P (P (P (P Zero)))) sMFive :: Sing Z (P (P (P (P (P Zero))))) -- | Add one to a singleton Z. sSucc :: Sing z -> Sing (Succ z) -- | Subtract one from a singleton Z. sPred :: Sing z -> Sing (Pred z) -- | Negate a singleton Z. sNegate :: Sing z -> Sing (Negate z) instance Show n => Show (Point n) instance Eq n => Eq (Point n) instance Enum n => Enum (Point n) instance Bounded n => Bounded (Point n) instance AdditiveGroup n => AffineSpace (Point n) -- | This module exports all the gubbins needed for type-checking your -- dimensioned quantities. See Metrology for some functions -- restricted to using a default LCSU, which is suitable for many -- applications. See also Vector for polymorphic functions -- suitable for use with the numerical classes from the -- vector-space package. module Data.Metrology.Poly -- | The number 0, polymorphic in its dimension. Use of this will often -- require a type annotation. zero :: Num n => Qu dimspec l n -- | Add two compatible quantities (|+|) :: (d1 @~ d2, Num n) => Qu d1 l n -> Qu d2 l n -> Qu d1 l n -- | Subtract two compatible quantities (|-|) :: (d1 @~ d2, Num n) => Qu d1 l n -> Qu d2 l n -> Qu d1 l n -- | Take the sum of a list of quantities qSum :: (Foldable f, Num n) => f (Qu d l n) -> Qu d l n -- | Negate a quantity qNegate :: Num n => Qu d l n -> Qu d l n -- | Multiply two quantities (|*|) :: Num n => Qu a l n -> Qu b l n -> Qu (Normalize (a @+ b)) l n -- | Divide two quantities (|/|) :: Fractional n => Qu a l n -> Qu b l n -> Qu (Normalize (a @- b)) l n -- | Multiply a quantity by a scalar from the left (*|) :: Num n => n -> Qu b l n -> Qu b l n -- | Multiply a quantity by a scalar from the right (|*) :: Num n => Qu a l n -> n -> Qu a l n -- | Divide a scalar by a quantity (/|) :: Fractional n => n -> Qu b l n -> Qu (Normalize ([] @- b)) l n -- | Divide a quantity by a scalar (|/) :: Fractional n => Qu a l n -> n -> Qu a l n -- | Raise a quantity to a integer power, knowing at compile time that the -- integer is non-negative. (|^) :: (NonNegative z, Num n) => Qu a l n -> Sing z -> Qu (a @* z) l n -- | Raise a quantity to a integer power known at compile time (|^^) :: Fractional n => Qu a l n -> Sing z -> Qu (a @* z) l n -- | Take the n'th root of a quantity, where n is known at compile time qNthRoot :: ((Zero < z) ~ True, Floating n) => Sing z -> Qu a l n -> Qu (a @/ z) l n -- | Square a quantity qSq :: Num n => Qu a l n -> Qu (Normalize (a @+ a)) l n -- | Cube a quantity qCube :: Num n => Qu a l n -> Qu (Normalize (Normalize (a @+ a) @+ a)) l n -- | Take the square root of a quantity qSqrt :: Floating n => Qu a l n -> Qu (a @/ Two) l n -- | Take the cubic root of a quantity qCubeRoot :: Floating n => Qu a l n -> Qu (a @/ Three) l n -- | Compare two quantities qCompare :: (d1 @~ d2, Ord n) => Qu d1 l n -> Qu d2 l n -> Ordering -- | Check if one quantity is less than a compatible one (|<|) :: (d1 @~ d2, Ord n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Check if one quantity is greater than a compatible one (|>|) :: (d1 @~ d2, Ord n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Check if one quantity is less than or equal to a compatible one (|<=|) :: (d1 @~ d2, Ord n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Check if one quantity is greater than or equal to a compatible one (|>=|) :: (d1 @~ d2, Ord n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Check if two quantities are equal (uses the equality of the underlying -- numerical type) (|==|) :: (d1 @~ d2, Eq n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Check if two quantities are not equal (|/=|) :: (d1 @~ d2, Eq n) => Qu d1 l n -> Qu d2 l n -> Bool -- | Compare two compatible quantities for approximate equality. If the -- difference between the left hand side and the right hand side -- arguments are less than or equal to the epsilon, they are -- considered equal. qApprox :: (d0 @~ d1, d0 @~ d2, Num n, Ord n) => Qu d0 l n -> Qu d1 l n -> Qu d2 l n -> Bool -- | Compare two compatible quantities for approixmate inequality. -- qNapprox e a b = not $ qApprox e a b qNapprox :: (d0 @~ d1, d0 @~ d2, Num n, Ord n) => Qu d0 l n -> Qu d1 l n -> Qu d2 l n -> Bool -- | Extracts a numerical value from a dimensioned quantity, expressed in -- the given unit. For example: -- --
--   inMeters :: Length -> Double
--   inMeters x = numIn x Meter
--   
-- -- or -- --
--   inMeters x = x # Meter   
--   
numIn :: (ValidDLU dim lcsu unit, Fractional n) => Qu dim lcsu n -> unit -> n -- | Infix synonym for numIn (#) :: (ValidDLU dim lcsu unit, Fractional n) => Qu dim lcsu n -> unit -> n -- | Creates a dimensioned quantity in the given unit. For example: -- --
--   height :: Length
--   height = quOf 2.0 Meter
--   
-- -- or -- --
--   height = 2.0 % Meter
--   
quOf :: (ValidDLU dim lcsu unit, Fractional n) => n -> unit -> Qu dim lcsu n -- | Infix synonym for quOf (%) :: (ValidDLU dim lcsu unit, Fractional n) => n -> unit -> Qu dim lcsu n -- | Show a dimensioned quantity in a given unit. (The default -- Show instance always uses units as specified in the LCSU.) showIn :: (ValidDLU dim lcsu unit, Fractional n, Show unit, Show n) => Qu dim lcsu n -> unit -> String -- | The number 1, expressed as a unitless dimensioned quantity. unity :: Num n => Qu [] l n -- | Cast between equivalent dimension within the same CSU. for example [kg -- m s] and [s m kg]. See the README for more info. redim :: d @~ e => Qu d l n -> Qu e l n -- | Dimension-keeping cast between different CSUs. convert :: (ConvertibleLCSUs d l1 l2, Fractional n) => Qu d l1 n -> Qu d l2 n -- | Use this to choose a default LCSU for a dimensioned quantity. The -- default LCSU uses the DefaultUnitOfDim representation for each -- dimension. defaultLCSU :: Qu dim DefaultLCSU n -> Qu dim DefaultLCSU n -- | Compute the argument in the DefaultLCSU, and present the -- result as lcsu-polymorphic dimension-polymorphic value. Named -- constant because one of its dominant usecase is to inject -- constant quantities into dimension-polymorphic expressions. constant :: (d @~ e, ConvertibleLCSUs e DefaultLCSU l, Fractional n) => Qu d DefaultLCSU n -> Qu e l n -- | Multiply two units to get another unit. For example: type -- MetersSquared = Meter :* Meter data (:*) u1 u2 (:*) :: u1 -> u2 -> (:*) u1 u2 -- | Divide two units to get another unit data (:/) u1 u2 (:/) :: u1 -> u2 -> (:/) u1 u2 -- | Raise a unit to a power, known at compile time data (:^) unit (power :: Z) (:^) :: unit -> Sing power -> (:^) unit -- | Multiply a conversion ratio by some constant. Used for defining -- prefixes. data (:@) prefix unit (:@) :: prefix -> unit -> (:@) prefix unit -- | A class for user-defined prefixes class UnitPrefix prefix multiplier :: (UnitPrefix prefix, Fractional f) => prefix -> f -- | Multiply two quantity types to produce a new one. For example: -- --
--   type Velocity = Length %/ Time
--   
-- | Divide two quantity types to produce a new one -- | Exponentiate a quantity type to an integer -- | Qu adds a dimensional annotation to its numerical value type -- n. This is the representation for all quantities. data Qu (a :: [Factor *]) (lcsu :: LCSU *) (n :: *) -- | Make a quantity type capable of storing a value of a given unit. This -- uses a Double for storage of the value. For example: -- --
--   data LengthDim = LengthDim
--   instance Dimension LengthDim
--   data Meter = Meter
--   instance Unit Meter where
--     type BaseUnit Meter = Canonical
--     type DimOfUnit Meter = LengthDim
--   type instance DefaultUnitOfDim LengthDim = Meter
--   type Length = MkQu_D LengthDim
--   
-- -- Note that the dimension must have an instance for the type -- family DefaultUnitOfDim for this to work. type MkQu_D dim = Qu (DimFactorsOf dim) DefaultLCSU Double -- | Make a quantity type with a custom numerical type and LCSU. type MkQu_DLN dim = Qu (DimFactorsOf dim) -- | Make a quantity type with a given unit. It will be stored as a -- Double. Note that the corresponding dimension must have -- an appropriate instance for DefaultUnitOfDim for this to work. type MkQu_U unit = Qu (DimFactorsOf (DimOfUnit unit)) DefaultLCSU Double -- | Make a quantity type with a unit and LCSU with custom numerical type. -- The quantity will have the dimension corresponding to the unit. type MkQu_ULN unit = Qu (DimFactorsOf (DimOfUnit unit)) -- | This class is used to mark abstract dimensions, such as -- Length, or Mass. class Dimension dim where type family DimFactorsOf dim :: [Factor *] type instance DimFactorsOf dim = '[F dim One] class DimOfUnitIsConsistent unit => Unit unit where type family BaseUnit unit :: * type family DimOfUnit unit :: * type family UnitFactorsOf unit :: [Factor *] type instance DimOfUnit unit = DimOfUnit (BaseUnit unit) type instance UnitFactorsOf unit = If (IsCanonical unit) '[F unit One] (UnitFactorsOf (BaseUnit unit)) conversionRatio _ = 1 canonicalConvRatio u = conversionRatio u * baseUnitRatio u conversionRatio :: Unit unit => unit -> Rational -- | Dummy type use just to label canonical units. It does not have -- a Unit instance. data Canonical -- | The dimension for the dimensionless quantities. It is also called -- "quantities of dimension one", but One is confusing with the -- type-level integer One. data Dimensionless Dimensionless :: Dimensionless -- | The unit for unitless dimensioned quantities data Number Number :: Number -- | The type of unitless dimensioned quantities. This is an instance of -- Num, though Haddock doesn't show it. This is parameterized by -- an LCSU and a number representation. type Count = MkQu_ULN Number -- | Convert a raw number into a unitless dimensioned quantity quantity :: n -> Qu [] l n -- | Make a local consistent set of units. The argument is a type-level -- list of tuple types, to be interpreted as an association list from -- dimensions to units. For example: -- --
--   type MyLCSU = MkLCSU '[(Length, Foot), (Mass, Gram), (Time, Year)]
--   
data LCSU star DefaultLCSU :: LCSU star -- | Assign a default unit for a dimension. Necessary only when using -- default LCSUs. -- | Check if an LCSU has consistent entries for the given unit. i.e. can -- the lcsu describe the unit? -- | Check if an LCSU can express the given dimension -- | Like ConvertibleLCSUs, but takes a dimension, not a dimension -- factors. -- | Check if the DefaultLCSU can convert into the given one, at the -- given dimension. -- | Check if the DefaultLCSU can convert into the given one, at the -- given unit. -- | Extract a dimension specifier from a list of factors -- | Extract a unit specifier from a list of factors -- | Extract a unit from a dimension factor list and an LCSU -- | The datatype for type-level integers. data Z Zero :: Z S :: Z -> Z P :: Z -> Z -- | Add one to an integer -- | Subtract one from an integer -- | Add two integers -- | Subtract two integers -- | Multiply two integers -- | Divide two integers -- | Negate an integer type One = S Zero type Two = S One type Three = S Two type Four = S Three type Five = S Four type MOne = P Zero type MTwo = P MOne type MThree = P MTwo type MFour = P MThree type MFive = P MFour -- | This is the singleton value representing Zero at the term -- level and at the type level, simultaneously. Used for raising units to -- powers. sZero :: Sing Z Zero sOne :: Sing Z (S Zero) sTwo :: Sing Z (S (S Zero)) sThree :: Sing Z (S (S (S Zero))) sFour :: Sing Z (S (S (S (S Zero)))) sFive :: Sing Z (S (S (S (S (S Zero))))) sMOne :: Sing Z (P Zero) sMTwo :: Sing Z (P (P Zero)) sMThree :: Sing Z (P (P (P Zero))) sMFour :: Sing Z (P (P (P (P Zero)))) sMFive :: Sing Z (P (P (P (P (P Zero))))) -- | Add one to a singleton Z. sSucc :: Sing z -> Sing (Succ z) -- | Subtract one from a singleton Z. sPred :: Sing z -> Sing (Pred z) -- | Negate a singleton Z. sNegate :: Sing z -> Sing (Negate z) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pZero :: Sing Z Zero -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pOne :: Sing Z (S Zero) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pTwo :: Sing Z (S (S Zero)) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pThree :: Sing Z (S (S (S Zero))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pFour :: Sing Z (S (S (S (S Zero)))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pFive :: Sing Z (S (S (S (S (S Zero))))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pMOne :: Sing Z (P Zero) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pMTwo :: Sing Z (P (P Zero)) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pMThree :: Sing Z (P (P (P Zero))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pMFour :: Sing Z (P (P (P (P Zero)))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pMFive :: Sing Z (P (P (P (P (P Zero))))) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pSucc :: Sing Z z -> Sing Z (Succ z) -- | Deprecated: The singleton prefix is changing from p to -- s. The p versions will be removed in a future -- release. pPred :: Sing Z z -> Sing Z (Pred z) -- | This module exports Template Haskell functions to make working with -- units a little more convenient. module Data.Metrology.TH -- | 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.) -- -- Note: Under GHC 7.10 and later, this function works only for base -- types like Length, not compound types like Volume or -- Velocity. See -- https://github.com/goldfirere/units/issues/34 for more info and -- a workaround. evalType :: Q Type -> Q Type -- | Declare a new dimension of the given name: -- --
--   $(declareDimension "Length")
--   
-- -- produces -- --
--   data Length = Length
--   instance Dimension Length
--   
declareDimension :: String -> Q [Dec] -- | 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"))
--   
declareCanonicalUnit :: String -> Q Type -> Maybe String -> Q [Dec] -- | 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"))
--   
declareDerivedUnit :: String -> Q Type -> Rational -> Maybe String -> Q [Dec] -- | 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). declareMonoUnit :: String -> Maybe String -> Q [Dec] -- | 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 :: ( Fractional n
--                , CompatibleUnit lcsu (Meter :/ Second :^ Two) )
--             => MkQu_ULN (Meter :/ Second :^ Two) lcsu n
--   gravity_g = 9.80665 % (undefined :: Meter :/ Second :^ Two)
--   
declareConstant :: String -> Rational -> Q Type -> Q [Dec] -- | Exports a class Quantity to allow easy conversion between -- proper quantities and types from other libraries. module Data.Metrology.Quantity -- | Quantity allows for easy conversions in and out of quantities. -- For example, say you are working with an outside library for time that -- defines UTCTime, where that stores the time measured in -- seconds. You could say -- --
--   instance Quantity UTCTime where
--     type QuantityUnit = Second
--     fromQuantity = ...
--     toQuantity = ...
--   
-- -- Then, conversions are easy and unit-safe. class Quantity t where type family QuantityUnit t :: * type family QuantityLCSU t :: LCSU * type family QuantityRep t :: * type instance QuantityLCSU t = DefaultLCSU type instance QuantityRep t = Double fromQuantity :: Quantity t => QuantityQu t -> t toQuantity :: Quantity t => t -> QuantityQu t -- | The Qu type associated with a member of the Quantity -- class type QuantityQu t = MkQu_ULN (QuantityUnit t) (QuantityLCSU t) (QuantityRep t) instance (ValidDL d l) => Quantity (Qu d l n) -- | The units package is a framework for strongly-typed dimensional -- analysis. This haddock documentation is generally not enough to -- be able to use this package effectively. Please see the readme at -- https://github.com/goldfirere/units/blob/master/README.md. -- -- Some of the types below refer to declarations that are not exported -- and not documented here. This is because Haddock does not allow -- finely-tuned abstraction in documentation. (In particular, right-hand -- sides of type synonym declarations are always included.) If a symbol -- is not exported, you do not need to know anything about it to -- use this package. -- -- Though it doesn't appear here, Count is an instance of -- Num, and generally has all the numeric instances that -- Double has. -- -- This module exports definitions that lack unit-polymorphism. If you -- wish to write more polymorphic code, see Poly. If you wish to -- use the numerical hierarchy from the vector-space package, -- see Vector. module Data.Metrology -- | Extracts a numerical value from a dimensioned quantity, expressed in -- the given unit. For example: -- --
--   inMeters :: Length -> Double
--   inMeters x = numIn x Meter
--   
-- -- or -- --
--   inMeters x = x # Meter   
--   
numIn :: (ValidDLU dim DefaultLCSU unit, Fractional n) => Qu dim DefaultLCSU n -> unit -> n -- | Infix synonym for numIn (#) :: (ValidDLU dim DefaultLCSU unit, Fractional n) => Qu dim DefaultLCSU n -> unit -> n -- | Creates a dimensioned quantity in the given unit. For example: -- --
--   height :: Length
--   height = quOf 2.0 Meter
--   
-- -- or -- --
--   height = 2.0 % Meter
--   
quOf :: (ValidDLU dim DefaultLCSU unit, Fractional n) => n -> unit -> Qu dim DefaultLCSU n -- | Infix synonym for quOf (%) :: (ValidDLU dim DefaultLCSU unit, Fractional n) => n -> unit -> Qu dim DefaultLCSU n -- | The type of unitless dimensioned quantities. This is an instance of -- Num, though Haddock doesn't show it. This assumes a default -- LCSU and an internal representation of Double. type Count = MkQu_U Number -- | This module exports functions allowing users to create their own unit -- quasiquoters to make for compact unit expressions. -- -- A typical use case is this: -- --
--   $(makeQuasiQuoter "unit" [''Kilo, ''Milli] [''Meter, ''Second])
--   
-- -- and then, in a separate module (due to GHC's staging -- constraints) -- --
--   x = 3 % [unit| m/s^2 ]
--   
-- -- The unit expressions can refer to the prefixes and units specified in -- the call to makeQuasiQuoter. The spellings of the prefixes and -- units are taken from their Show instances. -- -- The syntax for these expressions is like F#'s. There are four -- arithmetic operators (*, /, ^, and -- juxtaposition). Exponentiation binds the tightest, and it allows an -- integer to its right (possibly with minus signs and parentheses). Next -- tightest is juxtaposition, which indicates multiplication. Because -- juxtaposition binds tighter than division, the expressions -- m/s^2 and m/s s are equivalent. Multiplication and -- division bind the loosest and are left-associative, meaning that -- m/s*s is equivalent to (m/s)*s, probably not what -- you meant. Parentheses in unit expressions are allowed, of course. -- -- Within a unit string (that is, a unit with an optional prefix), there -- may be ambiguity. If a unit string can be interpreted as a unit -- without a prefix, that parsing is preferred. Thus, min would -- be minutes, not milli-inches (assuming appropriate prefixes and units -- available.) There still may be ambiguity between unit strings, even -- interpreting the string as a prefix and a base unit. If a unit string -- is amiguous in this way, it is rejected. For example, if we have -- prefixes da and d and units m and -- am, then dam is ambiguous like this. module Data.Metrology.Parser -- | makeQuasiQuoter "qq" prefixes units makes a quasi-quoter -- named qq that considers the prefixes and units provided. -- These are provided via names of the type constructors, -- not the data constructors. See the module documentation for -- more info and an example. makeQuasiQuoter :: String -> [Name] -> [Name] -> Q [Dec] -- | Gets a list of the names of all units with Show instances in -- scope. Example usage: -- --
--   $( do units <- allUnits
--         makeQuasiQuoter "unit" [] units )
--   
-- | Warning: Retrieving the list of all units and prefixes in scope -- does not work under GHC 7.8.*. Please upgrade GHC to use these -- functions. allUnits :: Q [Name] -- | Gets a list of the names of all unit prefixes with Show -- instances in scope. Example usage: -- --
--   $( do units    <- allUnits
--         prefixes <- allPrefixes
--         makeQuasiQuoter "unit" prefixes units )
--   
-- | Warning: Retrieving the list of all units and prefixes in scope -- does not work under GHC 7.8.*. Please upgrade GHC to use these -- functions. allPrefixes :: Q [Name] -- | Parse a unit expression, interpreted with respect the given symbol -- table. Returns either an error message or the successfully-parsed unit -- expression. parseUnit :: (Show pre, Show u) => SymbolTable pre u -> String -> Either String (UnitExp pre u) -- | Parsed unit expressions, parameterized by a prefix identifier type and -- a unit identifier type data UnitExp pre u -- | "1" Unity :: UnitExp pre u -- | a unit with, perhaps, a prefix Unit :: (Maybe pre) -> u -> UnitExp pre u Mult :: (UnitExp pre u) -> (UnitExp pre u) -> UnitExp pre u Div :: (UnitExp pre u) -> (UnitExp pre u) -> UnitExp pre u Pow :: (UnitExp pre u) -> Integer -> UnitExp pre u -- | A "symbol table" for the parser, mapping prefixes and units to their -- representations. data SymbolTable pre u -- | Build a symbol table from prefix mappings and unit mappings. The -- prefix mapping can be empty. This function checks to make sure that -- the strings are not inherently ambiguous and are purely alphabetic. mkSymbolTable :: (Show pre, Show u) => [(String, pre)] -> [(String, u)] -> Either String (SymbolTable pre u)