{-# 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 (Decimal p s -> Decimal p s -> Bool) -> (Decimal p s -> Decimal p s -> Bool) -> Eq (Decimal p s) forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Bool forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a $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 Eq, Eq (Decimal p s) Eq (Decimal p s) => (Decimal p s -> Decimal p s -> Ordering) -> (Decimal p s -> Decimal p s -> Bool) -> (Decimal p s -> Decimal p s -> Bool) -> (Decimal p s -> Decimal p s -> Bool) -> (Decimal p s -> Decimal p s -> Bool) -> (Decimal p s -> Decimal p s -> Decimal p s) -> (Decimal p s -> Decimal p s -> Decimal p s) -> Ord (Decimal p s) 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 $ccompare :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Ordering compare :: Decimal p s -> Decimal p s -> Ordering $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 >= :: Decimal p s -> Decimal p s -> Bool $cmax :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s max :: Decimal p s -> Decimal p s -> Decimal p s $cmin :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s min :: Decimal p s -> Decimal p s -> Decimal p s Ord, Int -> Decimal p s -> ShowS [Decimal p s] -> ShowS Decimal p s -> String (Int -> Decimal p s -> ShowS) -> (Decimal p s -> String) -> ([Decimal p s] -> ShowS) -> Show (Decimal p s) 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 $cshowsPrec :: forall (p :: Natural) (s :: Natural). Int -> Decimal p s -> ShowS showsPrec :: Int -> Decimal p s -> ShowS $cshow :: forall (p :: Natural) (s :: Natural). Decimal p s -> String show :: Decimal p s -> String $cshowList :: forall (p :: Natural) (s :: Natural). [Decimal p s] -> ShowS showList :: [Decimal p s] -> ShowS Show, ReadPrec [Decimal p s] ReadPrec (Decimal p s) Int -> ReadS (Decimal p s) ReadS [Decimal p s] (Int -> ReadS (Decimal p s)) -> ReadS [Decimal p s] -> ReadPrec (Decimal p s) -> ReadPrec [Decimal p s] -> Read (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 $creadsPrec :: forall (p :: Natural) (s :: Natural). Int -> ReadS (Decimal p s) readsPrec :: Int -> ReadS (Decimal p s) $creadList :: forall (p :: Natural) (s :: Natural). ReadS [Decimal p s] readList :: ReadS [Decimal p s] $creadPrec :: forall (p :: Natural) (s :: Natural). ReadPrec (Decimal p s) readPrec :: ReadPrec (Decimal p s) $creadListPrec :: forall (p :: Natural) (s :: Natural). ReadPrec [Decimal p s] readListPrec :: ReadPrec [Decimal p s] Read, Integer -> Decimal p s Decimal p s -> Decimal p s Decimal p s -> Decimal p s -> Decimal p s (Decimal p s -> Decimal p s -> Decimal p s) -> (Decimal p s -> Decimal p s -> Decimal p s) -> (Decimal p s -> Decimal p s -> Decimal p s) -> (Decimal p s -> Decimal p s) -> (Decimal p s -> Decimal p s) -> (Decimal p s -> Decimal p s) -> (Integer -> Decimal p s) -> Num (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 $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 * :: Decimal p s -> Decimal p s -> Decimal p s $cnegate :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s negate :: Decimal p s -> Decimal p s $cabs :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s abs :: Decimal p s -> Decimal p s $csignum :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s signum :: Decimal p s -> Decimal p s $cfromInteger :: forall (p :: Natural) (s :: Natural). Integer -> Decimal p s fromInteger :: Integer -> Decimal p s Num, Num (Decimal p s) Num (Decimal p s) => (Decimal p s -> Decimal p s -> Decimal p s) -> (Decimal p s -> Decimal p s) -> (Rational -> Decimal p s) -> Fractional (Decimal p s) 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 $c/ :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s -> Decimal p s / :: Decimal p s -> Decimal p s -> Decimal p s $crecip :: forall (p :: Natural) (s :: Natural). Decimal p s -> Decimal p s recip :: Decimal p s -> Decimal p s $cfromRational :: forall (p :: Natural) (s :: Natural). Rational -> Decimal p s fromRational :: Rational -> Decimal p s Fractional, Num (Decimal p s) Ord (Decimal p s) (Num (Decimal p s), Ord (Decimal p s)) => (Decimal p s -> Rational) -> Real (Decimal p s) 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 $ctoRational :: forall (p :: Natural) (s :: Natural). Decimal p s -> Rational toRational :: Decimal p s -> Rational Real) intScale :: D.BigDecimal -> Integer intScale :: BigDecimal -> Integer intScale = Natural -> Integer forall a. Integral a => a -> Integer toInteger (Natural -> Integer) -> (BigDecimal -> Natural) -> BigDecimal -> Integer 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 = BigDecimal -> Decimal p s forall (p :: Natural) (s :: Natural). BigDecimal -> Decimal p s Decimal (BigDecimal -> Decimal p s) -> BigDecimal -> Decimal p s forall a b. (a -> b) -> a -> b $ Integer -> Natural -> BigDecimal D.BigDecimal Integer n (Integer -> Natural forall a b. (Integral a, Num b) => a -> b fromIntegral (Integer -> Natural) -> Integer -> Natural forall a b. (a -> b) -> a -> b $ Proxy s -> Integer forall (n :: Natural) (proxy :: Natural -> *). KnownNat n => proxy n -> Integer natVal (Proxy s 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 = Proxy s -> Integer forall (n :: Natural) (proxy :: Natural -> *). KnownNat n => proxy n -> Integer natVal (Proxy s forall {k} (t :: k). Proxy t Proxy :: Proxy s) pp :: Integer pp = Proxy p -> Integer forall (n :: Natural) (proxy :: Natural -> *). KnownNat n => proxy n -> Integer natVal (Proxy p forall {k} (t :: k). Proxy t Proxy :: Proxy p) new :: BigDecimal new = if Integer ss Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool > BigDecimal -> Integer intScale BigDecimal d then Integer -> Natural -> BigDecimal D.BigDecimal (BigDecimal -> Integer D.value BigDecimal d Integer -> Integer -> Integer forall a. Num a => a -> a -> a * Integer 10 Integer -> Integer -> Integer forall a b. (Num a, Integral b) => a -> b -> a ^ (Integer ss Integer -> Integer -> Integer forall a. Num a => a -> a -> a - BigDecimal -> Integer intScale BigDecimal d)) (Integer -> Natural forall a b. (Integral a, Num b) => a -> b fromIntegral Integer ss) else BigDecimal -> RoundingAdvice -> BigDecimal D.roundBD BigDecimal d (Natural -> RoundingAdvice D.halfUp (Integer -> Natural forall a b. (Integral a, Num b) => a -> b fromIntegral Integer ss)) in if BigDecimal -> Natural D.precision BigDecimal new Natural -> Natural -> Bool forall a. Ord a => a -> a -> Bool > Integer -> Natural forall a b. (Integral a, Num b) => a -> b fromIntegral Integer pp then Maybe Int forall a. Maybe a Nothing else Int -> Maybe Int forall a. a -> Maybe a Just (Int -> Maybe Int) -> Int -> Maybe Int forall a b. (a -> b) -> a -> b $ Integer -> Int forall a. Num a => Integer -> a fromInteger (Integer -> Int) -> Integer -> Int forall a b. (a -> b) -> a -> b $ BigDecimal -> Integer D.value BigDecimal new