Copyright | © 2018 Phil de Joux © 2018 Block Scope Limited |
---|---|
License | MPL-2.0 |
Maintainer | Phil de Joux <phil.dejoux@blockscope.com> |
Stability | experimental |
Safe Haskell | None |
Language | Haskell2010 |
For encoding and decoding newtype quantities as scientific with a fixed number of decimal places and with units.
Usage
With these unit definitons;
[u| m |] [u| km = 1000 m |]
Let's say we have distances in kilometres we'd like encoded with 3 decimal places.
>>>
:{
newtype Distance a = Distance a deriving (Eq, Ord, Show) instance (q ~ Quantity Double [u| km |]) => DefaultDecimalPlaces (Distance q) where defdp _ = DecimalPlaces 3 instance (q ~ Quantity Double [u| km |]) => Newtype (Distance q) q where pack = Distance unpack (Distance a) = a :}
Encoding and decoding JSON.
>>>
:{
instance (q ~ Quantity Double [u| km |]) => ToJSON (Distance q) where toJSON x = toJSON $ ViaQ x instance (q ~ Quantity Double [u| km |]) => FromJSON (Distance q) where parseJSON o = do ViaQ x <- parseJSON o; return x :}
>>>
[u| 112233.445566 km |]
[u| 112233.445566 km |]>>>
encode (Distance [u| 112233.445566 km |])
"\"112233.446 km\"">>>
let Just x :: Maybe (Distance (Quantity Double [u| km |])) = decode (encode (Distance [u| 112233.445566 km |])) in x
Distance [u| 112233.446 km |]
Similarly for CSV.
>>>
:{
instance (q ~ Quantity Double [u| km |]) => ToField (Distance q) where toField x = toField $ ViaQ x instance (q ~ Quantity Double [u| km |]) => FromField (Distance q) where parseField c = do ViaQ x <- parseField c; return x :}
>>>
let d = Distance [u| 112233.445566 km |]
>>>
Csv.encode [("A", d)]
"A,112233.446 km\r\n">>>
Csv.decode NoHeader (Csv.encode [("B", d)]) == Right (fromList [("B", d)])
False>>>
Csv.decode NoHeader (Csv.encode [("C", d)]) == Right (fromList [("C", Distance [u| 112233.446 km |])])
True
Decimal Places and Units
data ViaQ n a u where Source #
An intermediate type used during encoding to JSON with aeson
and during
encoding to CSV with cassava
. It's also used during decoding.
The original type, a newtype Quantity
, goes to and fro via this
quantity so that the rational value can be encoded as a scientific value
with a fixed number of decimal places and with units.
ViaQ :: (DefaultDecimalPlaces n, Newtype n (Quantity a u)) => n -> ViaQ n a u |
(DefaultDecimalPlaces n, Newtype n (Quantity a u), Real a, KnownUnit (Unpack u)) => ToJSON (ViaQ n a u) Source # | |
(DefaultDecimalPlaces n, Newtype n (Quantity a u), Real a, Fractional a, KnownUnit (Unpack u)) => FromJSON (ViaQ n a u) Source # | |
(DefaultDecimalPlaces n, Newtype n (Quantity a u), Real a, Fractional a, KnownUnit (Unpack u)) => FromField (ViaQ n a u) Source # | |
(DefaultDecimalPlaces n, Newtype n (Quantity a u), Real a, KnownUnit (Unpack u)) => ToField (ViaQ n a u) Source # | |