{- | Copyright : Copyright (C) 2006-2014 Bjorn Buckwalter License : BSD3 Maintainer : bjorn@buckwalter.se Stability : Stable Portability: GHC only? Defines types for manipulation of units and quantities without phantom types for their dimensions. -} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE ScopedTypeVariables #-} module Numeric.Units.Dimensional.Dynamic ( -- * Dynamic Quantities AnyQuantity , demoteQuantity, promoteQuantity -- * Dynamic Units , AnyUnit , demoteUnit, promoteUnit ) where import Numeric.Units.Dimensional.Prelude hiding (lookup) import Numeric.Units.Dimensional.Coercion import Numeric.Units.Dimensional.UnitNames (UnitName, baseUnitName) import Data.ExactPi import Data.Proxy -- | A 'Quantity' whose 'Dimension' is only known dynamically. data AnyQuantity v = AnyQuantity Dimension' v deriving (Eq) instance (Show v) => Show (AnyQuantity v) where show (AnyQuantity d v) = (show v) ++ " " ++ (show . baseUnitName $ d) instance HasDimension (AnyQuantity v) where dimension (AnyQuantity d _) = d -- | Converts a 'Quantity' of statically known 'Dimension' into an 'AnyQuantity'. demoteQuantity :: forall d v.(KnownDimension d) => Quantity d v -> AnyQuantity v demoteQuantity (Quantity val) = AnyQuantity dim val where dim = dimension (Proxy :: Proxy d) -- | Converts an 'AnyQuantity' into a 'Quantity' of statically known 'Dimension', or 'Nothing' if the dimension does not match. promoteQuantity :: forall d v.(KnownDimension d) => AnyQuantity v -> Maybe (Quantity d v) promoteQuantity (AnyQuantity dim val) | dim == dim' = Just . Quantity $ val | otherwise = Nothing where dim' = dimension (Proxy :: Proxy d) -- | A 'Unit' whose 'Dimension' is only known dynamically. data AnyUnit = AnyUnit Dimension' (UnitName 'NonMetric) ExactPi instance Show AnyUnit where show (AnyUnit _ n e) = "1 " ++ (show n) ++ " =def= " ++ (show e) ++ " of the SI base unit" instance HasDimension AnyUnit where dimension (AnyUnit d _ _) = d -- | Converts a 'Unit' of statically known 'Dimension' into an 'AnyUnit'. demoteUnit :: forall a d v.(KnownDimension d) => Unit a d v -> AnyUnit demoteUnit u = AnyUnit dim (name $ weaken u) (exactValue u) where dim = dimension (Proxy :: Proxy d) -- | Converts an 'AnyUnit' into a 'Unit' of statically known 'Dimension', or 'Nothing' if the dimension does not match. -- -- The result is represented in 'ExactPi', conversion to other representations is possible using 'changeRepApproximate'. promoteUnit :: forall d.(KnownDimension d) => AnyUnit -> Maybe (Unit 'NonMetric d ExactPi) promoteUnit (AnyUnit dim n e) | dim == dim' = Just $ mkUnitR n e siUnit | otherwise = Nothing where dim' = dimension (Proxy :: Proxy d)