penny-lib- Extensible double-entry accounting system - library

Safe HaskellSafe-Inferred



Penny quantities. A quantity is simply a count (possibly fractional) of something. It does not have a commodity or a Debit/Credit.



data Qty Source

A quantity is always greater than zero. Various odd questions happen if quantities can be zero. For instance, what if you have a debit whose quantity is zero? Does it require a balancing credit that is also zero? And how can you have a debit of zero anyway?

I can imagine situations where a quantity of zero might be useful; for instance maybe you want to specifically indicate that a particular posting in a transaction did not happen (for instance, that a paycheck deduction did not take place). I think the better way to handle that though would be through an addition to Debit/Credit - maybe Debit/Credit/Zero. Barring the addition of that, though, the best way to indicate a situation such as this would be through transaction memos.

WARNING - before doing comparisons or equality tests

The Eq instance is derived. Therefore q1 == q2 only if q1 and q2 have both the same mantissa and the same exponent. You may instead want equivalent. Similarly, the Ord instance is derived. It compares based on the integral value of the mantissa and of the exponent. You may instead want compareQty, which compares after equalizing the exponents.

data NumberStr Source


Whole String

A whole number only. No radix point.

WholeRad String

A whole number and a radix point, but nothing after the radix point.

WholeRadFrac String String

A whole number and something after the radix point.

RadFrac String

A radix point and a fractional value after it, but nothing before the radix point.


toQty :: NumberStr -> Maybe QtySource

Converts strings to Qty. Fails if any of the strings have non-digits, or if any are negative, or if the result is not greater than zero, or if the strings are empty.

prettyShowQty :: Qty -> StringSource

Shows a quantity, nicely formatted after accounting for both the mantissa and decimal places, e.g. 0.232 or 232.12 or whatever.

compareQty :: Qty -> Qty -> OrderingSource

Compares Qty after equalizing their exponents.

 compareQty (newQty 15 1) (newQty 1500 3) == EQ

add :: Qty -> Qty -> QtySource

difference :: Qty -> Qty -> DifferenceSource

Subtract the second Qty from the first, after equalizing their exponents.

allocate :: Qty -> (Qty, [Qty]) -> (Qty, [Qty])Source

Allocate a Qty proportionally so that the sum of the results adds up to a given Qty. Fails if the allocation cannot be made (e.g. if it is impossible to allocate without overflowing Decimal.) The result will always add up to the given sum.



:: TotSeats

Total number of seats in the legislature. This is the integer that will be allocated. This number must be positive or this function will fail at runtime.

-> [PartyVotes]

The total seats will be allocated proportionally depending on how many votes each party received. The sum of this list must be positive, and each member of the list must be at least zero; otherwise a runtime error will occur.

-> [SeatsWon]

The sum of this list will always be equal to the total number of seats, and its length will always be equal to length of the PartyVotes list.

Allocates integers using the largest remainder method. This is the method used to allocate parliamentary seats in many countries, so the types are named accordingly.

qtyOne :: QtySource

Mantissa 1, exponent 0