{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Number.DimensionTerm where
import qualified Algebra.DimensionTerm as Dim
import qualified Algebra.OccasionallyScalar as OccScalar
import qualified Algebra.Module as Module
import qualified Algebra.Algebraic as Algebraic
import qualified Algebra.Field as Field
import qualified Algebra.Absolute as Absolute
import qualified Algebra.Ring as Ring
import qualified Algebra.Additive as Additive
import Algebra.Field ((/), fromRational', )
import Algebra.Ring ((*), one, fromInteger, )
import Algebra.Additive ((+), (-), zero, negate, )
import Algebra.Module ((*>), )
import System.Random (Random, randomR, random)
import Control.DeepSeq (NFData(rnf), )
import Data.Tuple.HT (mapFst, )
import NumericPrelude.Base
import Prelude ()
newtype T u a = Cons a
deriving (Eq, Ord)
instance (Dim.C u, Show a) => Show (T u a) where
showsPrec p x =
let disect :: T u a -> (u,a)
disect (Cons y) = (undefined, y)
(u,z) = disect x
in showParen (p >= Dim.appPrec)
(showString "DimensionNumber.fromNumberWithDimension " . showsPrec Dim.appPrec u .
showString " " . showsPrec Dim.appPrec z)
instance NFData a => NFData (T u a) where
rnf (Cons x) = rnf x
fromNumber :: a -> Scalar a
fromNumber = Cons
toNumber :: Scalar a -> a
toNumber (Cons x) = x
fromNumberWithDimension :: Dim.C u => u -> a -> T u a
fromNumberWithDimension _ = Cons
toNumberWithDimension :: Dim.C u => u -> T u a -> a
toNumberWithDimension _ (Cons x) = x
instance (Dim.C u, Additive.C a) => Additive.C (T u a) where
zero = Cons zero
(Cons a) + (Cons b) = Cons (a+b)
(Cons a) - (Cons b) = Cons (a-b)
negate (Cons a) = Cons (negate a)
instance (Dim.C u, Module.C a b) => Module.C a (T u b) where
a *> (Cons b) = Cons (a *> b)
instance (Dim.IsScalar u, Ring.C a) => Ring.C (T u a) where
one = Cons one
(Cons a) * (Cons b) = Cons (a*b)
fromInteger a = Cons (fromInteger a)
instance (Dim.IsScalar u, Field.C a) => Field.C (T u a) where
(Cons a) / (Cons b) = Cons (a/b)
recip (Cons a) = Cons (Field.recip a)
fromRational' a = Cons (fromRational' a)
instance (Dim.IsScalar u, OccScalar.C a b) => OccScalar.C a (T u b) where
toScalar =
OccScalar.toScalar . toNumber . rewriteDimension Dim.toScalar
toMaybeScalar =
OccScalar.toMaybeScalar . toNumber . rewriteDimension Dim.toScalar
fromScalar =
rewriteDimension Dim.fromScalar . fromNumber . OccScalar.fromScalar
instance (Dim.C u, Random a) => Random (T u a) where
randomR (Cons l, Cons u) = mapFst Cons . randomR (l,u)
random = mapFst Cons . random
infixl 7 &*&, *&
infixl 7 &/&
(&*&) :: (Dim.C u, Dim.C v, Ring.C a) =>
T u a -> T v a -> T (Dim.Mul u v) a
(&*&) (Cons x) (Cons y) = Cons (x Ring.* y)
(&/&) :: (Dim.C u, Dim.C v, Field.C a) =>
T u a -> T v a -> T (Dim.Mul u (Dim.Recip v)) a
(&/&) (Cons x) (Cons y) = Cons (x Field./ y)
mulToScalar :: (Dim.C u, Ring.C a) =>
T u a -> T (Dim.Recip u) a -> a
mulToScalar x y = cancelToScalar (x &*& y)
divToScalar :: (Dim.C u, Field.C a) =>
T u a -> T u a -> a
divToScalar x y = cancelToScalar (x &/& y)
cancelToScalar :: (Dim.C u) =>
T (Dim.Mul u (Dim.Recip u)) a -> a
cancelToScalar =
toNumber . rewriteDimension Dim.cancelRight
recip :: (Dim.C u, Field.C a) =>
T u a -> T (Dim.Recip u) a
recip (Cons x) = Cons (Field.recip x)
unrecip :: (Dim.C u, Field.C a) =>
T (Dim.Recip u) a -> T u a
unrecip (Cons x) = Cons (Field.recip x)
sqr :: (Dim.C u, Ring.C a) =>
T u a -> T (Dim.Sqr u) a
sqr x = x &*& x
sqrt :: (Dim.C u, Algebraic.C a) =>
T (Dim.Sqr u) a -> T u a
sqrt (Cons x) = Cons (Algebraic.sqrt x)
abs :: (Dim.C u, Absolute.C a) => T u a -> T u a
abs (Cons x) = Cons (Absolute.abs x)
absSignum :: (Dim.C u, Absolute.C a) => T u a -> (T u a, a)
absSignum x0@(Cons x) = (abs x0, Absolute.signum x)
scale, (*&) :: (Dim.C u, Ring.C a) =>
a -> T u a -> T u a
scale x (Cons y) = Cons (x Ring.* y)
(*&) = scale
rewriteDimension :: (Dim.C u, Dim.C v) => (u -> v) -> T u a -> T v a
rewriteDimension _ (Cons x) = Cons x
type Scalar a = T Dim.Scalar a
type Length a = T Dim.Length a
type Time a = T Dim.Time a
type Mass a = T Dim.Mass a
type Charge a = T Dim.Charge a
type Angle a = T Dim.Angle a
type Temperature a = T Dim.Temperature a
type Information a = T Dim.Information a
type Frequency a = T Dim.Frequency a
type Voltage a = T Dim.Voltage a
scalar :: a -> Scalar a
scalar = fromNumber
length :: a -> Length a
length = Cons
time :: a -> Time a
time = Cons
mass :: a -> Mass a
mass = Cons
charge :: a -> Charge a
charge = Cons
frequency :: a -> Frequency a
frequency = Cons
angle :: a -> Angle a
angle = Cons
temperature :: a -> Temperature a
temperature = Cons
information :: a -> Information a
information = Cons
voltage :: a -> Voltage a
voltage = Cons