simple-units-1.0.1.0: src/Units/Simple/Quantity.hs
{-# OPTIONS_GHC -Wno-missing-methods #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Units.Simple.Quantity
( Quantity (..)
) where
import GHC.TypeLits
import Units.Simple.Unit
-- |A numerical quantity with some associated unit.
-- Units are not created directly with this constructor,
-- but through the individual unit functions.
--
-- Examples:
--
-- >>> meter -- a unitary quantity associated to meters.
-- 1 m
-- >>> 2.5*ampere -- constructing through literal arithmetic
-- 2.5 A
-- >>> candela' 3.14 -- constructing through the unit constructors
-- 3.14 cd
-- >>> :set -XDataKinds
-- >>> 2 :: Quantity (SingleUnit 'Second) Rational
-- 2 % 1 s
--
-- Associated units are represented through a phantom parameter of the 'Units' kind synonym.
-- These are currently implemented as a type-level pair of lists representing the power
-- to which each unit is raised. Units can be inspected through 'showUnits'.
--
-- New constructors may be written by combining the provided ones, such as
--
-- >>> let newton = kilogram .* meter ./ (second .* second)
-- >>> 23*newton
-- 23.0 kg*m/s^2
-- <BLANKLINE>
-- >>> let g = 6.67408e-11 * newton .* (meter .* meter) ./ (kilogram .* kilogram)
-- >>> g -- gravitational constant
-- 6.67408e-11 m^3/kg*s^2
-- >>> let gravity m1 m2 r = g .* (m1 * kilogram) .* (m2 * kilogram) ./ (r*meter .* r*meter)
-- >>> let earth_mass = 5.972e24 * kilo gram
-- >>> let mars_mass = 6.417e23 * kilo gram
-- >>> let earth_radius = 6371 * kilo meter
-- >>> let mars_radius = 3389.5 * kilo meter
-- >>> let weight_on_earth mass = gravity mass earth_mass earth_radius
-- >>> let weight_on_mars mass = gravity mass mars_mass mars_radius
-- >>> weight_on_earth (80 * kilo gram)
-- 785.5719790179963 kg*m/s^2
-- >>> weight_on_mars (80 * kilo gram)
-- 298.22370259533704 kg*m/s^2
-- >>> weight_on_mars 1 / weight_on_earth 1
-- 0.3796261966575378
newtype Quantity (us :: Units) a =
Quantity {
fromQuantity :: a -- ^Unwraps a 'Quantity', losing all unit information
}
deriving ( Eq
, Ord
, Enum
, Num
, Real
, Integral
, Fractional
, Floating
, Functor
)
instance (KnownSymbol (UnitRepr us), Show a) => Show (Quantity us a) where
show (Quantity x) = show x <> " " <> showUnits @us
instance Applicative (Quantity us) where
pure = Quantity
Quantity f <*> Quantity x = Quantity (f x)