{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} module Data.Avro.Schema.Decimal where import qualified Data.BigDecimal as D import Data.Proxy import GHC.TypeLits newtype Decimal (p :: Nat) (s :: Nat) = Decimal { 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 a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Bool /= :: Decimal p s -> Decimal p s -> Bool $c/= :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Bool == :: Decimal p s -> Decimal p s -> Bool $c== :: forall (p :: Nat) (s :: Nat). 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 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 forall (p :: Nat) (s :: Nat). Eq (Decimal p s) forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Bool forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Ordering forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Decimal p s min :: Decimal p s -> Decimal p s -> Decimal p s $cmin :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Decimal p s max :: Decimal p s -> Decimal p s -> Decimal p s $cmax :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Decimal p s >= :: Decimal p s -> Decimal p s -> Bool $c>= :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Bool > :: Decimal p s -> Decimal p s -> Bool $c> :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Bool <= :: Decimal p s -> Decimal p s -> Bool $c<= :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Bool < :: Decimal p s -> Decimal p s -> Bool $c< :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Bool compare :: Decimal p s -> Decimal p s -> Ordering $ccompare :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Ordering $cp1Ord :: forall (p :: Nat) (s :: Nat). Eq (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 a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a forall (p :: Nat) (s :: Nat). Int -> Decimal p s -> ShowS forall (p :: Nat) (s :: Nat). [Decimal p s] -> ShowS forall (p :: Nat) (s :: Nat). Decimal p s -> String showList :: [Decimal p s] -> ShowS $cshowList :: forall (p :: Nat) (s :: Nat). [Decimal p s] -> ShowS show :: Decimal p s -> String $cshow :: forall (p :: Nat) (s :: Nat). Decimal p s -> String showsPrec :: Int -> Decimal p s -> ShowS $cshowsPrec :: forall (p :: Nat) (s :: Nat). Int -> 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 a. (Int -> ReadS a) -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a forall (p :: Nat) (s :: Nat). ReadPrec [Decimal p s] forall (p :: Nat) (s :: Nat). ReadPrec (Decimal p s) forall (p :: Nat) (s :: Nat). Int -> ReadS (Decimal p s) forall (p :: Nat) (s :: Nat). ReadS [Decimal p s] readListPrec :: ReadPrec [Decimal p s] $creadListPrec :: forall (p :: Nat) (s :: Nat). ReadPrec [Decimal p s] readPrec :: ReadPrec (Decimal p s) $creadPrec :: forall (p :: Nat) (s :: Nat). ReadPrec (Decimal p s) readList :: ReadS [Decimal p s] $creadList :: forall (p :: Nat) (s :: Nat). ReadS [Decimal p s] readsPrec :: Int -> ReadS (Decimal p s) $creadsPrec :: forall (p :: Nat) (s :: Nat). 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 (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 a. (a -> a -> a) -> (a -> a -> a) -> (a -> a -> a) -> (a -> a) -> (a -> a) -> (a -> a) -> (Integer -> a) -> Num a forall (p :: Nat) (s :: Nat). Integer -> Decimal p s forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Decimal p s fromInteger :: Integer -> Decimal p s $cfromInteger :: forall (p :: Nat) (s :: Nat). Integer -> Decimal p s signum :: Decimal p s -> Decimal p s $csignum :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s abs :: Decimal p s -> Decimal p s $cabs :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s negate :: Decimal p s -> Decimal p s $cnegate :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s * :: Decimal p s -> Decimal p s -> Decimal p s $c* :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Decimal p s - :: Decimal p s -> Decimal p s -> Decimal p s $c- :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Decimal p s + :: Decimal p s -> Decimal p s -> Decimal p s $c+ :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> 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 a. Num a -> (a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a forall (p :: Nat) (s :: Nat). Num (Decimal p s) forall (p :: Nat) (s :: Nat). Rational -> Decimal p s forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Decimal p s fromRational :: Rational -> Decimal p s $cfromRational :: forall (p :: Nat) (s :: Nat). Rational -> Decimal p s recip :: Decimal p s -> Decimal p s $crecip :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s / :: Decimal p s -> Decimal p s -> Decimal p s $c/ :: forall (p :: Nat) (s :: Nat). Decimal p s -> Decimal p s -> Decimal p s $cp1Fractional :: forall (p :: Nat) (s :: Nat). Num (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 a. Num a -> Ord a -> (a -> Rational) -> Real a forall (p :: Nat) (s :: Nat). Num (Decimal p s) forall (p :: Nat) (s :: Nat). Ord (Decimal p s) forall (p :: Nat) (s :: Nat). Decimal p s -> Rational toRational :: Decimal p s -> Rational $ctoRational :: forall (p :: Nat) (s :: Nat). Decimal p s -> Rational $cp2Real :: forall (p :: Nat) (s :: Nat). Ord (Decimal p s) $cp1Real :: forall (p :: Nat) (s :: Nat). Num (Decimal p s) Real) fromUnderlyingValue :: forall p s. KnownNat s => Integer -> Decimal p s fromUnderlyingValue :: Integer -> Decimal p s fromUnderlyingValue Integer n = BigDecimal -> Decimal p s forall (p :: Nat) (s :: Nat). BigDecimal -> Decimal p s Decimal (BigDecimal -> Decimal p s) -> BigDecimal -> Decimal p s forall a b. (a -> b) -> a -> b $ Integer -> Integer -> BigDecimal D.BigDecimal Integer n (Proxy s -> Integer forall (n :: Nat) (proxy :: Nat -> *). 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 :: Decimal p s -> Maybe Int underlyingValue (Decimal BigDecimal d) = let ss :: Integer ss = Proxy s -> Integer forall (n :: Nat) (proxy :: Nat -> *). 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 :: Nat) (proxy :: Nat -> *). 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 D.getScale BigDecimal d then Integer -> Integer -> BigDecimal D.BigDecimal (BigDecimal -> Integer D.getValue 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 D.getScale BigDecimal d)) Integer ss else BigDecimal -> MathContext -> BigDecimal D.roundBD BigDecimal d (Integer -> MathContext D.halfUp Integer ss) in if BigDecimal -> Integer D.precision BigDecimal new Integer -> Integer -> Bool forall a. Ord a => a -> a -> Bool > 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.getValue BigDecimal new