{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RoleAnnotations #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.UnitsOfMeasure.Internal
(
Unit
, type One
, type Base
, type (*:)
, type (/:)
, type (^:)
, Quantity(..)
, unQuantity
, zero
, mk
, (+:)
, (*:)
, (-:)
, negate'
, abs'
, signum'
, fromInteger'
, (/:)
, recip'
, fromRational'
, toRational'
, sqrt'
, UnitSyntax(..)
, Unpack
, Pack
, Prod
, type (~~)
, MkUnit
) where
import Control.DeepSeq
import Foreign.Storable
import GHC.Exts (Constraint)
import GHC.TypeLits (Symbol, Nat, type (-))
data Unit
type family One :: Unit where
type Base :: Symbol -> Unit
type family Base b where
type (*:) :: Unit -> Unit -> Unit
type family u *: v where
type (/:) :: Unit -> Unit -> Unit
type family u /: v where
type (^:) :: Unit -> Nat -> Unit
type family u ^: n where
u ^: 0 = One
u ^: 1 = u
u ^: n = u *: (u ^: (n-1))
infixl 6 +:, -:
infixl 7 *:, /:
infixr 8 ^:
newtype Quantity a (u :: Unit) = MkQuantity a
type role Quantity representational nominal
deriving instance Bounded a => Bounded (Quantity a u)
deriving instance Eq a => Eq (Quantity a u)
deriving instance Ord a => Ord (Quantity a u)
deriving instance (Enum a, u ~ One) => Enum (Quantity a u)
deriving instance (Floating a, u ~ One) => Floating (Quantity a u)
deriving instance (Fractional a, u ~ One) => Fractional (Quantity a u)
deriving instance (Integral a, u ~ One) => Integral (Quantity a u)
deriving instance (Num a, u ~ One) => Num (Quantity a u)
deriving instance (Real a, u ~ One) => Real (Quantity a u)
deriving instance (RealFloat a, u ~ One) => RealFloat (Quantity a u)
deriving instance (RealFrac a, u ~ One) => RealFrac (Quantity a u)
deriving instance Storable a => Storable (Quantity a u)
deriving instance NFData a => NFData (Quantity a u)
unQuantity :: Quantity a u -> a
unQuantity :: forall a (u :: Unit). Quantity a u -> a
unQuantity (MkQuantity a
x) = a
x
zero :: Num a => Quantity a u
zero :: forall a (u :: Unit). Num a => Quantity a u
zero = a -> Quantity a u
forall a (u :: Unit). a -> Quantity a u
MkQuantity a
0
mk :: a -> Quantity a One
mk :: forall a. a -> Quantity a One
mk = a -> Quantity a One
forall a (u :: Unit). a -> Quantity a u
MkQuantity
(+:) :: Num a => Quantity a u -> Quantity a u -> Quantity a u
MkQuantity a
x +: :: forall a (u :: Unit).
Num a =>
Quantity a u -> Quantity a u -> Quantity a u
+: MkQuantity a
y = a -> Quantity a u
forall a (u :: Unit). a -> Quantity a u
MkQuantity (a
x a -> a -> a
forall a. Num a => a -> a -> a
+ a
y)
{-# INLINE (+:) #-}
(*:) :: (Num a, w ~~ u *: v) => Quantity a u -> Quantity a v -> Quantity a w
MkQuantity a
x *: :: forall a (w :: Unit) (u :: Unit) (v :: Unit).
(Num a, w ~~ (u *: v)) =>
Quantity a u -> Quantity a v -> Quantity a w
*: MkQuantity a
y = a -> Quantity a w
forall a (u :: Unit). a -> Quantity a u
MkQuantity (a
x a -> a -> a
forall a. Num a => a -> a -> a
* a
y)
{-# INLINE (*:) #-}
(-:) :: Num a => Quantity a u -> Quantity a u -> Quantity a u
MkQuantity a
x -: :: forall a (u :: Unit).
Num a =>
Quantity a u -> Quantity a u -> Quantity a u
-: MkQuantity a
y = a -> Quantity a u
forall a (u :: Unit). a -> Quantity a u
MkQuantity (a
x a -> a -> a
forall a. Num a => a -> a -> a
- a
y)
{-# INLINE (-:) #-}
negate' :: Num a => Quantity a u -> Quantity a u
negate' :: forall a (u :: Unit). Num a => Quantity a u -> Quantity a u
negate' (MkQuantity a
x) = a -> Quantity a u
forall a (u :: Unit). a -> Quantity a u
MkQuantity (a -> a
forall a. Num a => a -> a
negate a
x)
{-# INLINE negate' #-}
abs' :: Num a => Quantity a u -> Quantity a u
abs' :: forall a (u :: Unit). Num a => Quantity a u -> Quantity a u
abs' (MkQuantity a
x) = a -> Quantity a u
forall a (u :: Unit). a -> Quantity a u
MkQuantity (a -> a
forall a. Num a => a -> a
abs a
x)
{-# INLINE abs' #-}
signum' :: Num a => Quantity a u -> Quantity a One
signum' :: forall a (u :: Unit). Num a => Quantity a u -> Quantity a One
signum' (MkQuantity a
x) = a -> Quantity a One
forall a (u :: Unit). a -> Quantity a u
MkQuantity (a -> a
forall a. Num a => a -> a
signum a
x)
{-# INLINE signum' #-}
fromInteger' :: Integral a => Quantity Integer u -> Quantity a u
fromInteger' :: forall a (u :: Unit).
Integral a =>
Quantity Integer u -> Quantity a u
fromInteger' (MkQuantity Integer
x) = a -> Quantity a u
forall a (u :: Unit). a -> Quantity a u
MkQuantity (Integer -> a
forall a. Num a => Integer -> a
fromInteger Integer
x)
{-# INLINE fromInteger' #-}
(/:) :: (Fractional a, w ~~ u /: v) => Quantity a u -> Quantity a v -> Quantity a w
MkQuantity a
x /: :: forall a (w :: Unit) (u :: Unit) (v :: Unit).
(Fractional a, w ~~ (u /: v)) =>
Quantity a u -> Quantity a v -> Quantity a w
/: MkQuantity a
y = a -> Quantity a w
forall a (u :: Unit). a -> Quantity a u
MkQuantity (a
x a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
y)
{-# INLINE (/:) #-}
recip' :: (Fractional a, w ~~ One /: u) => Quantity a u -> Quantity a w
recip' :: forall a (w :: Unit) (u :: Unit).
(Fractional a, w ~~ (One /: u)) =>
Quantity a u -> Quantity a w
recip' (MkQuantity a
x) = a -> Quantity a w
forall a (u :: Unit). a -> Quantity a u
MkQuantity (a -> a
forall a. Fractional a => a -> a
recip a
x)
{-# INLINE recip' #-}
fromRational' :: Fractional a => Quantity Rational u -> Quantity a u
fromRational' :: forall a (u :: Unit).
Fractional a =>
Quantity Rational u -> Quantity a u
fromRational' (MkQuantity Rational
x) = a -> Quantity a u
forall a (u :: Unit). a -> Quantity a u
MkQuantity (Rational -> a
forall a. Fractional a => Rational -> a
fromRational Rational
x)
{-# INLINE fromRational' #-}
toRational' :: Real a => Quantity a u -> Quantity Rational u
toRational' :: forall a (u :: Unit). Real a => Quantity a u -> Quantity Rational u
toRational' (MkQuantity a
x) = Rational -> Quantity Rational u
forall a (u :: Unit). a -> Quantity a u
MkQuantity (a -> Rational
forall a. Real a => a -> Rational
toRational a
x)
{-# INLINE toRational' #-}
sqrt' :: (Floating a, w ~~ u ^: 2) => Quantity a w -> Quantity a u
sqrt' :: forall a (w :: Unit) (u :: Unit).
(Floating a, w ~~ (u ^: 2)) =>
Quantity a w -> Quantity a u
sqrt' (MkQuantity a
x) = a -> Quantity a u
forall a (u :: Unit). a -> Quantity a u
MkQuantity (a -> a
forall a. Floating a => a -> a
sqrt a
x)
{-# INLINE sqrt' #-}
data UnitSyntax s = [s] :/ [s]
deriving (UnitSyntax s -> UnitSyntax s -> Bool
(UnitSyntax s -> UnitSyntax s -> Bool)
-> (UnitSyntax s -> UnitSyntax s -> Bool) -> Eq (UnitSyntax s)
forall s. Eq s => UnitSyntax s -> UnitSyntax s -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall s. Eq s => UnitSyntax s -> UnitSyntax s -> Bool
== :: UnitSyntax s -> UnitSyntax s -> Bool
$c/= :: forall s. Eq s => UnitSyntax s -> UnitSyntax s -> Bool
/= :: UnitSyntax s -> UnitSyntax s -> Bool
Eq, Int -> UnitSyntax s -> ShowS
[UnitSyntax s] -> ShowS
UnitSyntax s -> String
(Int -> UnitSyntax s -> ShowS)
-> (UnitSyntax s -> String)
-> ([UnitSyntax s] -> ShowS)
-> Show (UnitSyntax s)
forall s. Show s => Int -> UnitSyntax s -> ShowS
forall s. Show s => [UnitSyntax s] -> ShowS
forall s. Show s => UnitSyntax s -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall s. Show s => Int -> UnitSyntax s -> ShowS
showsPrec :: Int -> UnitSyntax s -> ShowS
$cshow :: forall s. Show s => UnitSyntax s -> String
show :: UnitSyntax s -> String
$cshowList :: forall s. Show s => [UnitSyntax s] -> ShowS
showList :: [UnitSyntax s] -> ShowS
Show)
type Pack :: UnitSyntax Symbol -> Unit
type family Pack u where
Pack (xs :/ ys) = Prod xs /: Prod ys
type Prod :: [Symbol] -> Unit
type family Prod xs where
Prod '[] = One
Prod (x ': xs) = Base x *: Prod xs
type Unpack :: Unit -> UnitSyntax Symbol
type family Unpack u where
type (~~) :: Unit -> Unit -> Constraint
type family u ~~ v where
infix 4 ~~
type MkUnit :: Symbol -> Unit
type family MkUnit s