1 {-# LANGUAGE DeriveDataTypeable #-}
2 {-# LANGUAGE FlexibleInstances #-}
3 {-# LANGUAGE StandaloneDeriving #-}
4 {-# OPTIONS_GHC -fno-warn-orphans #-}
5 module Hcompta.Quantity where
8 import Data.Data (Data)
9 import Data.Decimal (Decimal, DecimalRaw(..), roundTo)
10 import Data.Eq (Eq(..))
11 import qualified Data.Foldable as Foldable
12 import Data.Map.Strict (Map)
13 import qualified Data.Map.Strict as Map
14 import Data.Ord (Ord(..), Ordering(..))
15 import Data.Word (Word8)
16 import Prelude (Integer, Integral, Num(..), fromIntegral)
17 import Text.Show (Show)
25 quantity_null :: a -> Bool
32 ) => Zero (Map unit q) where
33 quantity_zero = Map.empty
34 quantity_null = Foldable.all quantity_null
35 instance Zero Integer where
37 quantity_null = (==) 0
38 instance Zero Decimal where
40 quantity_null = (==) 0
42 quantity_sign :: (Zero q, Ord q) => q -> Ordering
45 _ | quantity_null q -> EQ
46 _ | q < quantity_zero -> LT
50 class (Data a, Show a) => Addable a where
51 quantity_add :: a -> a -> a
52 instance Addable Integer where
54 instance Addable Decimal where
56 Decimal e (fromIntegral (n1 + n2))
57 where (e, n1, n2) = decimal_round_min d1 d2
58 instance -- Map unit quantity
63 ) => Addable (Map unit quantity) where
64 quantity_add = Map.unionWith quantity_add
67 class (Data a, Show a) => Negable a where
68 quantity_neg :: a -> a
69 instance Negable Integer where
71 instance Negable Decimal where
73 instance -- Map unit quantity
78 ) => Negable (Map unit quantity) where
79 quantity_neg = Map.map quantity_neg
82 class (Data a, Show a) => Subable a where
83 quantity_sub :: a -> a -> a
84 instance Subable Integer where
91 ) => Subable (Map unit quantity) where
92 quantity_sub = Map.unionWith quantity_sub
94 -- * Type 'Decimal' (with orphan Data instance)
97 deriving instance Data Decimal
99 -- | Round the two 'DecimalRaw' values to the smallest exponent.
105 decimal_round_min d1@(Decimal e1 _) d2@(Decimal e2 _) = (e, n1, n2)
108 Decimal _ n1 = roundTo e d1
109 Decimal _ n2 = roundTo e d2