smarter handling of priced amounts. Normalising and some basic arithmetic now preserve prices.
Currently, amounts with the same commodity but different prices are kept separate. Useful ?
This commit is contained in:
		
							parent
							
								
									54ee68976b
								
							
						
					
					
						commit
						4c97ca5514
					
				| @ -55,14 +55,22 @@ instance Num Amount where | ||||
|     (-) = amountop (-) | ||||
|     (*) = amountop (*) | ||||
| 
 | ||||
| instance Ord Amount where | ||||
|     compare (Amount ac aq ap) (Amount bc bq bp) = compare (ac,aq,ap) (bc,bq,bp) | ||||
| 
 | ||||
| instance Num MixedAmount where | ||||
|     fromInteger i = Mixed [Amount (comm "") (fromInteger i) Nothing] | ||||
|     negate (Mixed as) = Mixed $ map negate as | ||||
|     negate (Mixed as) = Mixed $ map negateAmountPreservingPrice as | ||||
|     (+) (Mixed as) (Mixed bs) = normaliseMixedAmount $ Mixed $ filter (not . isZeroAmount) $ as ++ bs | ||||
|     (*)    = error "programming error, mixed amounts do not support multiplication" | ||||
|     abs    = error "programming error, mixed amounts do not support abs" | ||||
|     signum = error "programming error, mixed amounts do not support signum" | ||||
| 
 | ||||
| instance Ord MixedAmount where | ||||
|     compare (Mixed as) (Mixed bs) = compare as bs | ||||
| 
 | ||||
| negateAmountPreservingPrice a = (-a){price=price a} | ||||
| 
 | ||||
| -- | Apply a binary arithmetic operator to two amounts - converting to the | ||||
| -- second one's commodity, adopting the lowest precision, and discarding | ||||
| -- any price information. (Using the second commodity is best since sum | ||||
| @ -136,14 +144,20 @@ showMixedAmountOrZero a | ||||
|     | isZeroMixedAmount a = "0" | ||||
|     | otherwise = showMixedAmount a | ||||
| 
 | ||||
| -- | Simplify a mixed amount by combining any of its component amounts | ||||
| -- which have the same commodity. | ||||
| -- | Simplify a mixed amount by combining any component amounts which have | ||||
| -- the same commodity and the same price. | ||||
| normaliseMixedAmount :: MixedAmount -> MixedAmount | ||||
| normaliseMixedAmount (Mixed as) = Mixed $ map sum $ grouped | ||||
| normaliseMixedAmount (Mixed as) = Mixed as' | ||||
|     where  | ||||
|       grouped = [filter (hassymbol s) as | s <- symbols] | ||||
|       symbols = sort $ nub $ map (symbol . commodity) as | ||||
|       hassymbol s a = s == (symbol $ commodity a) | ||||
|       as' = map sumAmountsPreservingPrice $ group $ sort as | ||||
|       sort = sortBy cmpsymbolandprice | ||||
|       cmpsymbolandprice a1 a2 = compare (sym a1,price a1) (sym a2,price a2) | ||||
|       group = groupBy samesymbolandprice  | ||||
|       samesymbolandprice a1 a2 = (sym a1 == sym a2) && (price a1 == price a2) | ||||
|       sym = symbol . commodity | ||||
| 
 | ||||
| sumAmountsPreservingPrice [] = nullamt | ||||
| sumAmountsPreservingPrice as = (sum as){price=price $ head as} | ||||
| 
 | ||||
| -- | Convert a mixed amount's component amounts to the commodity of their | ||||
| -- saved price, if any. | ||||
|  | ||||
| @ -13,7 +13,7 @@ import qualified Data.Map as Map | ||||
| 
 | ||||
| type AccountName = String | ||||
| 
 | ||||
| data Side = L | R deriving (Eq,Show)  | ||||
| data Side = L | R deriving (Eq,Show,Ord)  | ||||
| 
 | ||||
| data Commodity = Commodity { | ||||
|       symbol :: String,  -- ^ the commodity's symbol | ||||
| @ -23,7 +23,7 @@ data Commodity = Commodity { | ||||
|       spaced :: Bool,    -- ^ should there be a space between symbol and quantity | ||||
|       comma :: Bool,     -- ^ should thousands be comma-separated | ||||
|       precision :: Int   -- ^ number of decimal places to display | ||||
|     } deriving (Eq,Show) | ||||
|     } deriving (Eq,Show,Ord) | ||||
| 
 | ||||
| data Amount = Amount { | ||||
|       commodity :: Commodity, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user