{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE UndecidableInstances #-} module Literate.Accounting.Amount where import Control.Monad.Trans.Except as MT import Control.Monad.Trans.Reader as MT import Data.Data (Data) import Data.Ratio (Rational) import GHC.Real (FractionalExponentBase (Base10), Ratio ((:%)), (%)) import GHC.TypeLits (KnownNat, Nat, Symbol, natVal, type (<=)) import Literate.Accounting.Quantity import Literate.Accounting.Unit import Literate.Prelude import Text.Read (Read) import Text.Show (Show (..), ShowS, showParen, showString, showsPrec) newtype Amount (qf :: Nat) (unit :: Unit) = Amount { amountQuantity :: Quantity qf } deriving (Show, Read, Eq, Ord, Data, Typeable, Generic) instance QuantFact qf => FromInteger (MT.Except ErrorQuantity (Amount qf unit)) where fromInteger i = fromRational (i :% 1) instance QuantFact qf => FromInteger (Amount qf unit) where fromInteger = fromInteger >>> Amount instance Addable (Amount qf unit) where Amount x + Amount y = Amount (x + y) sumAmounts :: forall qf unit f. Functor f => Foldable f => f (Amount qf unit) -> Maybe (Amount qf unit) sumAmounts l = l <&> amountQuantity & sumQuantities <&> Amount instance QuantFact qf => FromRational (MT.Except ErrorQuantity (Amount qf unit)) where fromRational r = Amount <$> fromRational r instance QuantFact qf => FromRational (Amount qf unit) where fromRational = Amount . fromRational -- instance QuantFact qf => FromRational (Amount qf unit) where -- fromRational = either (throw @_ @_ @ErrorQuantity) id . MT.runExcept . fromRational {- sum :: forall f. Foldable f => f Amount -> Maybe Amount sum l = let maxBoundI :: Integer maxBoundI = fromIntegral (maxBound :: Word64) r :: Integer r = foldl' (\acc a -> (toInteger :: Word64 -> Integer) (amountQuantity a) + acc) 0 l in if r > maxBoundI then Nothing else Just (Amount ((fromInteger :: Integer -> Word64) r)) -}