{-# LANGUAGE TypeFamilies, TypeOperators, DataKinds #-} module Tests.Compile.Readme where import Data.Metrology.Poly hiding (LCSU) data LengthDim = LengthDim -- each dimension is a datatype that acts as its own proxy instance Dimension LengthDim data TimeDim = TimeDim instance Dimension TimeDim type VelocityDim = LengthDim :/ TimeDim data Meter = Meter instance Unit Meter where -- declare Meter as a Unit type BaseUnit Meter = Canonical -- Meters are "canonical" type DimOfUnit Meter = LengthDim -- Meters measure Lengths instance Show Meter where -- Show instances are optional but useful show _ = "m" -- do *not* examine the argument! data Foot = Foot instance Unit Foot where type BaseUnit Foot = Meter -- Foot is defined in terms of Meter conversionRatio _ = 0.3048 -- do *not* examine the argument! -- We don't need to specify the `DimOfUnit`; -- it's implied by the `BaseUnit`. instance Show Foot where show _ = "ft" data Second = Second instance Unit Second where type BaseUnit Second = Canonical type DimOfUnit Second = TimeDim instance Show Second where show _ = "s" type LCSU = MkLCSU '[(LengthDim, Meter), (TimeDim, Second)] type Length = MkQu_DLN LengthDim LCSU Double -- Length stores lengths in our defined LCSU, using `Double` as the numerical type type Length' = MkQu_ULN Foot LCSU Double -- same as Length. Note the `U` in `MkQu_ULN`, allowing it to take a unit type Time = MkQu_DLN TimeDim LCSU Double extend :: Length -> Length -- a function over lengths extend x = redim $ x |+| (1 % Meter) inMeters :: Length -> Double -- extract the # of meters inMeters = (# Meter) -- more on this later conversion :: Length -- mixing units conversion = (4 % Meter) |+| (10 % Foot) vel :: Length %/ Time -- The `%*` and `%/` operators allow -- you to combine types vel = (3 % Meter) |/| (2 % Second) data Kilo = Kilo instance UnitPrefix Kilo where multiplier _ = 1000 kilo :: unit -> Kilo :@ unit kilo = (Kilo :@) longWayAway :: Length longWayAway = 150 % kilo Meter longWayAwayInMeters :: Double longWayAwayInMeters = longWayAway # Meter -- 150000.0 type MetersPerSecond = Meter :/ Second type Velocity1 = MkQu_ULN MetersPerSecond LCSU Double speed :: Velocity1 speed = 20 % (Meter :/ Second) type Velocity2 = Length %/ Time -- same type as Velocity1 type MetersSquared = Meter :^ Two type Area1 = MkQu_ULN MetersSquared LCSU Double type Area2 = Length %^ Two -- same type as Area1 roomSize :: Area1 roomSize = 100 % (Meter :^ sTwo) roomSize' :: Area1 roomSize' = 100 % (Meter :* Meter) type Velocity3 = (MkQu_ULN Number LCSU Double) %/ Time %* Length addVels :: Velocity1 -> Velocity1 -> Velocity3 addVels v1 v2 = redim $ (v1 |+| v2) type instance DefaultUnitOfDim LengthDim = Meter type instance DefaultUnitOfDim TimeDim = Second -- type Length = MkQu_D LengthDim