{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} module Data.Avro.Schema.Decimal ( Decimal , fromUnderlyingValue , underlyingValue ) where import qualified Data.BigDecimal as D import Data.Proxy import GHC.TypeLits newtype Decimal (p :: Nat) (s :: Nat) = Decimal { forall (p :: Natural) (s :: Natural). Decimal p s -> BigDecimal unDecimal :: D.BigDecimal } deriving (Decimal p s -> Decimal p s -> Bool forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Bool forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: Decimal p s -> Decimal p s -> Bool $c/= :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Bool == :: Decimal p s -> Decimal p s -> Bool $c== :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Bool Eq, Decimal p s -> Decimal p s -> Bool Decimal p s -> Decimal p s -> Ordering Decimal p s -> Decimal p s -> Decimal p s forall (p :: Natural) (s :: Natural). Eq (Decimal p s) forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Bool forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Ordering forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s forall a. Eq a -> (a -> a -> Ordering) -> (a -> a -> Bool) -> (a -> a -> Bool) -> (a -> a -> Bool) -> (a -> a -> Bool) -> (a -> a -> a) -> (a -> a -> a) -> Ord a min :: Decimal p s -> Decimal p s -> Decimal p s $cmin :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s max :: Decimal p s -> Decimal p s -> Decimal p s $cmax :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s >= :: Decimal p s -> Decimal p s -> Bool $c>= :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Bool > :: Decimal p s -> Decimal p s -> Bool $c> :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Bool <= :: Decimal p s -> Decimal p s -> Bool $c<= :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Bool < :: Decimal p s -> Decimal p s -> Bool $c< :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Bool compare :: Decimal p s -> Decimal p s -> Ordering $ccompare :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Ordering Ord, Int -> Decimal p s -> ShowS forall (p :: Natural) (s :: Natural). Int -> Decimal p s -> ShowS forall (p :: Natural) (s :: Natural). [Decimal p s] -> ShowS forall (p :: Natural) (s :: Natural). Decimal p s -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [Decimal p s] -> ShowS $cshowList :: forall (p :: Natural) (s :: Natural). [Decimal p s] -> ShowS show :: Decimal p s -> String $cshow :: forall (p :: Natural) (s :: Natural). Decimal p s -> String showsPrec :: Int -> Decimal p s -> ShowS $cshowsPrec :: forall (p :: Natural) (s :: Natural). Int -> Decimal p s -> ShowS Show, ReadPrec [Decimal p s] ReadPrec (Decimal p s) ReadS [Decimal p s] forall (p :: Natural) (s :: Natural). ReadPrec [Decimal p s] forall (p :: Natural) (s :: Natural). ReadPrec (Decimal p s) forall (p :: Natural) (s :: Natural). Int -> ReadS (Decimal p s) forall (p :: Natural) (s :: Natural). ReadS [Decimal p s] forall a. (Int -> ReadS a) -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a readListPrec :: ReadPrec [Decimal p s] $creadListPrec :: forall (p :: Natural) (s :: Natural). ReadPrec [Decimal p s] readPrec :: ReadPrec (Decimal p s) $creadPrec :: forall (p :: Natural) (s :: Natural). ReadPrec (Decimal p s) readList :: ReadS [Decimal p s] $creadList :: forall (p :: Natural) (s :: Natural). ReadS [Decimal p s] readsPrec :: Int -> ReadS (Decimal p s) $creadsPrec :: forall (p :: Natural) (s :: Natural). Int -> ReadS (Decimal p s) Read, Integer -> Decimal p s Decimal p s -> Decimal p s Decimal p s -> Decimal p s -> Decimal p s forall (p :: Natural) (s :: Natural). Integer -> Decimal p s forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s forall a. (a -> a -> a) -> (a -> a -> a) -> (a -> a -> a) -> (a -> a) -> (a -> a) -> (a -> a) -> (Integer -> a) -> Num a fromInteger :: Integer -> Decimal p s $cfromInteger :: forall (p :: Natural) (s :: Natural). Integer -> Decimal p s signum :: Decimal p s -> Decimal p s $csignum :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s abs :: Decimal p s -> Decimal p s $cabs :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s negate :: Decimal p s -> Decimal p s $cnegate :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s * :: Decimal p s -> Decimal p s -> Decimal p s $c* :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s - :: Decimal p s -> Decimal p s -> Decimal p s $c- :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s + :: Decimal p s -> Decimal p s -> Decimal p s $c+ :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s Num, Rational -> Decimal p s Decimal p s -> Decimal p s Decimal p s -> Decimal p s -> Decimal p s forall (p :: Natural) (s :: Natural). Num (Decimal p s) forall (p :: Natural) (s :: Natural). Rational -> Decimal p s forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s forall a. Num a -> (a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a fromRational :: Rational -> Decimal p s $cfromRational :: forall (p :: Natural) (s :: Natural). Rational -> Decimal p s recip :: Decimal p s -> Decimal p s $crecip :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s / :: Decimal p s -> Decimal p s -> Decimal p s $c/ :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s Fractional, Decimal p s -> Rational forall (p :: Natural) (s :: Natural). Num (Decimal p s) forall (p :: Natural) (s :: Natural). Ord (Decimal p s) forall (p :: Natural) (s :: Natural). Decimal p s -> Rational forall a. Num a -> Ord a -> (a -> Rational) -> Real a toRational :: Decimal p s -> Rational $ctoRational :: forall (p :: Natural) (s :: Natural). Decimal p s -> Rational Real) intScale :: D.BigDecimal -> Integer intScale :: BigDecimal -> Integer intScale = forall a. Integral a => a -> Integer toInteger forall b c a. (b -> c) -> (a -> b) -> a -> c . BigDecimal -> Natural D.scale fromUnderlyingValue :: forall p s. KnownNat s => Integer -> Decimal p s fromUnderlyingValue :: forall (p :: Natural) (s :: Natural). KnownNat s => Integer -> Decimal p s fromUnderlyingValue Integer n = forall (p :: Natural) (s :: Natural). BigDecimal -> Decimal p s Decimal forall a b. (a -> b) -> a -> b $ Integer -> Natural -> BigDecimal D.BigDecimal Integer n (forall a b. (Integral a, Num b) => a -> b fromIntegral forall a b. (a -> b) -> a -> b $ forall (n :: Natural) (proxy :: Natural -> *). KnownNat n => proxy n -> Integer natVal (forall {k} (t :: k). Proxy t Proxy :: Proxy s)) underlyingValue :: forall s p. (KnownNat p, KnownNat s) => Decimal p s -> Maybe Int underlyingValue :: forall (s :: Natural) (p :: Natural). (KnownNat p, KnownNat s) => Decimal p s -> Maybe Int underlyingValue (Decimal BigDecimal d) = let ss :: Integer ss = forall (n :: Natural) (proxy :: Natural -> *). KnownNat n => proxy n -> Integer natVal (forall {k} (t :: k). Proxy t Proxy :: Proxy s) pp :: Integer pp = forall (n :: Natural) (proxy :: Natural -> *). KnownNat n => proxy n -> Integer natVal (forall {k} (t :: k). Proxy t Proxy :: Proxy p) new :: BigDecimal new = if Integer ss forall a. Ord a => a -> a -> Bool > BigDecimal -> Integer intScale BigDecimal d then Integer -> Natural -> BigDecimal D.BigDecimal (BigDecimal -> Integer D.value BigDecimal d forall a. Num a => a -> a -> a * Integer 10 forall a b. (Num a, Integral b) => a -> b -> a ^ (Integer ss forall a. Num a => a -> a -> a - BigDecimal -> Integer intScale BigDecimal d)) (forall a b. (Integral a, Num b) => a -> b fromIntegral Integer ss) else BigDecimal -> RoundingAdvice -> BigDecimal D.roundBD BigDecimal d (Natural -> RoundingAdvice D.halfUp (forall a b. (Integral a, Num b) => a -> b fromIntegral Integer ss)) in if BigDecimal -> Natural D.precision BigDecimal new forall a. Ord a => a -> a -> Bool > forall a b. (Integral a, Num b) => a -> b fromIntegral Integer pp then forall a. Maybe a Nothing else forall a. a -> Maybe a Just forall a b. (a -> b) -> a -> b $ forall a. Num a => Integer -> a fromInteger forall a b. (a -> b) -> a -> b $ BigDecimal -> Integer D.value BigDecimal new