Fraser Tweedale
March 17, 2023
79

# A tax combinator library could be useful for Rules-as-Code [lightning talk]

Lightning talk at Everything Open 2023.

I demonstrate the Haskell /tax/ library and introduce /tax-ato/,
a library for Australian personal income tax calculations.

March 17, 2023

## Transcript

1. ### A tax combinator library could be useful for Rules as

Code or: surely you didn’t think you’d escape without hearing me talk about Haskell? Fraser Tweedale @[email protected] March 16, 2023
2. ### Rates Rebate Act 1973 (NZ) s 3(1) A ratepayer who,

at the commencement of a rating year, was the ratepayer of a residential property is entitled, on application in that year, to a rebate of— (a) so much of the rates payable for that rating year in respect of the property as represents— (i) two-thirds of the amount by which those rates exceed \$160, reduced by— (ii) \$1 for each \$8 by which the ratepayer’s income for the preceding tax year exceeded \$28,080, that last-mentioned amount being increased by \$500 in respect of each person who was a dependant of the ratepayer at the commencement of the rating year in respect of which the application is made; or (b) \$700,— whichever amount is smaller.
3. ### incomeThreshold :: Natural -> Money Rational incomeThreshold numDependants = Money

(28080 + fromIntegral numDependants * 500) reduction :: Natural -> Tax (Money Rational) (Money Rational) reduction numDependants = above (incomeThreshold numDependants ) ( -1/8) rebate :: Natural -> Money Rational -> Tax (Money Rational) (Money Rational) rebate numDependants income = lesserOf ( lump (Money 700)) ( greaterOf ( lump (Money 0)) ( above (Money 160) (2/3) <> lump ( getTax (reduction numDependants ) income )))
4. ### Combinators: functions that compose smaller computations into a more complex

computation. . . that (typically) follow some laws. . . such that our ability to reason about the computation can scale as it grows.

0.02)
6. ### lowIncomeTaxOffset = limit (Money 0) ( lump (Money ( -445))

<> above (Money 37000) 0.015 )
7. ### individualIncomeTax = marginal’ [ ( 18200 , 0.19 ) ,

( 45000 , 0.325 - 0.19 ) , (120000 , 0.37 - 0.325) , (180000 , 0.45 - 0.37 ) ]
8. ### data Tax b a = Tax { getTax :: b

-> a } deriving ( Semigroup, Monoid, Functor, Profunctor )
9. ### allTheTaxes = individualIncomeTax <> medicareLevy (Money 23226) <> lowIncomeTaxOffset weeklyWithholding

= dimap (\$* 52) (\$/ 52) allTheTaxes fnlyWithholding = dimap (\$* 26) (\$/ 26) allTheTaxes monthlyWithholding = dimap (\$* 12) (\$/ 12) allTheTaxes
10. ### https://hackage.haskell.org/package/tax https://github.com/frasertweedale/hs-tax blog post: https://is.gd/tax_combinators useful for "Rules as Code"

calculations relating to tax, levies, rates, rebates, payroll...

12. ### hs-tax-ato: stuﬀ that’s implemented individual income tax, employee share schemes

Medicare levy, Medicare levy surcharge HELP (HECS/SFSS student loans) deductions oﬀsets: low income, LMITO, spouse contribution private health insurance rebate adjustments dividends, CGT, foreign income, foreign income tax oﬀset rates/rules for previous ﬁnancial years (back to 2017)
13. ### hs-tax-ato: stuﬀ that’s NOT implemented PAYG instalments (coming soon) some

adjustments/variations based on family income or dependents partnership/trust/personal services income super income streams and lump payments some "grandfathering" rules (e.g. CGT indexation method) lots of other esoteric (to me) features and quirks
14. ### hs-tax-ato: known issues needs updates for 2022–23 FY (coming soon)

missing some rounding steps lack of usage examples