content: {-# LANGUAGE ConstraintKinds, DataKinds, FlexibleContexts, TypeFamilies,
               TypeOperators, ImplicitParams, CPP #-}
  {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
  
  #if __GLASGOW_HASKELL__ >= 711
  {-# OPTIONS_GHC -fconstraint-solver-iterations=10 #-}
  #endif
  
  module Tests.PhysicalConstants where
  
  import Data.Metrology.Poly
  import Data.Metrology.Show ()
  import Data.Metrology.SI.Poly
  import qualified Data.Dimensions.SI 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
  
  -}
  