units-2.1: Tests/PhysicalConstants.hs
{-# LANGUAGE ConstraintKinds, DataKinds, FlexibleContexts, TypeFamilies,
TypeOperators, ImplicitParams #-}
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
module Tests.PhysicalConstants where
import Data.Metrology.Poly
import Data.Metrology.Show ()
import Data.Metrology.SI.Poly
import qualified Data.Metrology.SI.Dims as D
import Tests.Compile.MetrologySynonyms
import Test.Tasty.HUnit
import Test.HUnit.Approx
----------------------------------------------------------------
-- Mass units
----------------------------------------------------------------
type instance DefaultUnitOfDim D.Mass = Kilo :@ Gram
type instance DefaultUnitOfDim D.Time = Second
type instance DefaultUnitOfDim D.Length = Meter
type instance DefaultUnitOfDim D.Current = Ampere
type instance DefaultUnitOfDim D.Temperature = Kelvin
-- | A unicornhorn of honor (unicornhorn in short) is the historical
-- unit of length used in Kingdom of Fantasia. A unicornhorn was
-- defined as the length of the horn of the King's honored
-- unicorn. Unfortunately, king's men did not documented their
-- technology, so today there's no telling how long a unicornhorn was.
data UnicornHorn = UnicornHorn
instance Unit UnicornHorn where
type BaseUnit UnicornHorn = Canonical
type DimOfUnit UnicornHorn = D.Length
instance Show UnicornHorn where
show _ = "uhoh"
type MkQu_UL unit lcsu = MkQu_ULN unit lcsu Double
type KingdomUnit = MkLCSU '[ (D.Length, UnicornHorn) ]
solarMass :: DefaultConvertibleLCSU_D D.Mass l => Mass l Double
solarMass = constant $ 1.98892e33 % Gram
earthMass :: DefaultConvertibleLCSU_D D.Mass l => Mass l Double
earthMass = constant $ 5.9742e24 % Gram
electronMass :: DefaultConvertibleLCSU_D D.Mass l => Mass l Double
electronMass = constant $ 9.10938291e-28 % Gram
protonMass :: DefaultConvertibleLCSU_D D.Mass l => Mass l Double
protonMass = constant $ 1.67262178e-24 % Gram
speedOfLight :: DefaultConvertibleLCSU_D D.Velocity l => Velocity l Double
speedOfLight = constant $ 299792458 % ((Second :^ sMOne) :* Meter)
elementaryCharge :: DefaultConvertibleLCSU_D D.Charge l => Charge l Double
elementaryCharge = constant $ 1.60217657e-19 % Coulomb
gravitationalConstant :: DefaultConvertibleLCSU_U SIGCUnit l => MkQu_UL SIGCUnit l
gravitationalConstant = constant $ 6.67384e-11 % (undefined :: SIGCUnit)
kB :: DefaultConvertibleLCSU_U SIkBUnit l => MkQu_UL SIkBUnit l
kB = constant $ 1.3806488e-23 % (undefined :: SIkBUnit)
-- RAE: problem solved. :)
planckLength :: DefaultConvertibleLCSU_D D.Length l => Length l Double
planckLength = constant $ qSqrt (hbar |*| gravitationalConstant |/| (speedOfLight |^ sThree))
planckTime :: DefaultConvertibleLCSU_D D.Time l => Time l Double
planckTime = constant $ planckLength |/| speedOfLight
-- eps0
vacuumPermittivity :: CompatibleUnit l SIPermittivityUnit
=> MkQu_UL SIPermittivityUnit l
vacuumPermittivity =
(1 / (4 * pi * 1e-7 * 299792458**2)) % (undefined :: SIPermittivityUnit)
-- mu0
vacuumPermeability :: CompatibleUnit l SIPermeabilityUnit
=> MkQu_UL SIPermeabilityUnit l
vacuumPermeability = (4 * pi * 1e-7) % (undefined :: SIPermeabilityUnit)
-- |Planck constant
planckConstant :: CompatibleUnit l JouleSecond
=> MkQu_UL JouleSecond l
planckConstant = (6.6260695729e-34) % (undefined :: JouleSecond)
-- |Reduced Planck constant
hbar :: CompatibleUnit l JouleSecond => MkQu_UL JouleSecond l
hbar = (1 / 2 / pi) *| planckConstant
tests =
let ?epsilon = 1e-40 in
testCase "PhysicalConstants" ((planckLength :: Length SI Double) # Meter @?~ 1.616199e-35)
main :: IO ()
main = do
putStrLn "typechecks!"
print (planckLength :: Length SI Double)
-- print (planckLength :: Length KingdomUnit Double)
-- last line does not typecheck -- good!
{- output --
typechecks!
1.616199256057012e-35 m
-}