Preface

Goal: Progressive Tax Rate Formula in Haskell

I found a good income taxes case to be written in Haskell. Yes it is the progressive tax tariff formula in functional programming.

Following regulation in my country the tarrifs is defined as below:

Progressively

    0 until 50  million:  5%
>  50 until 250 million: 15%
> 250 until 500 million: 25%
> 500 million          : 30%

Cumulative equation in math can be described as below:

Latex Math: Cumulative Tax Equation

Spreadsheet Version

I have wrote an article in my local language, about making progressive tax tariff formula in spreadsheet:

Challenge

I found that the Excel function is very nice. So short that it only takes this one line:

=max( ({5;15;25;30}%*$PPh) - {0;5;30;55}*10^6 )

Can I do this shorter in Haskell ?

Short answer: No!

But I found that Haskell can solve this issue very nicely.

Meanwhile

It is after midnight here, so tired after attending a night class in campus. But I have promise myself to finish this article.


Simple Example

Calculation

With simple calculation using math the tarrif is as below:

  50 million:   2.5 million
 250 million:  32.5 million
 500 million:  95   million
1000 million: 245   million

All in Rupiah currency.

Matplotlib Chart

With matplotlib we can plot above equation to this chart below:

Matplotlib: Cumulative Tax Equation

Actually, this chart above is not very helpful. In order to have better understanding, we need infographic below.

Infographic Chart

Haskell: Progressive Tax Tariff Chart


Haskell Code

Typecast

Consider start writing code, with very simple typecast from Real to Integer.

-- taxable income
pkp :: Float
pkp = 1000000000

main = do
   print $ round pkp

This will show

1000000000

You can use either Float type. If you need better precision, you may consider Double type.

Using Function

Be lazy. Learn Haskell!

The next step is write down what I did in paper step by step, in function. Since Haskell is lazy and pure functional, the order of the function does not matter.

-- taxable income
pkp :: Double
pkp = 1000000000

-- income tax using progressive tariff
(t1, t2, t3) = (50000000, 250000000, 500000000)

pph :: Double -> Double
pph pkp = if pkp <= t1
             then pph_t1 pkp
             else pph_t2 pkp

pph_t1 :: Double -> Double
pph_t1 pkp = pkp * 0.05 

pph_t2 :: Double -> Double
pph_t2 pkp = if pkp <= t2 
                then (pkp - t1) * 0.15 + pph_t1(t1)
                else pph_t3 pkp

pph_t3 :: Double -> Double
pph_t3 pkp = if pkp <= t3
                then (pkp - t2) * 0.25 + pph_t2(t2)
                else pph_t4 pkp

pph_t4 :: Double -> Double
pph_t4 pkp = (pkp - t3) * 0.30 + pph_t3(t3)

main = do
   print $ round $ pph pkp

Code above will result as below

245000000

Actually the code above does not looks good. We can rephrase the sentence above to better code poetry.

Using Guard and Recursive Function

Guard combined with Recursive Function, can resolve the function very nicely.

-- taxable income
pkp :: Double
pkp = 1000000000

-- income tax using progressive tariff
pph :: Double -> Double
pph pkp = pkpr pkp
  where
    (t1, t2, t3)  = (50000000, 250000000, 500000000)
    pkpr pkp
      | pkp <= t1 = pkp * 0.05
      | pkp <= t2 = (pkp - t1) * 0.15 + pph t1
      | pkp <= t3 = (pkp - t2) * 0.25 + pph t2
      | otherwise = (pkp - t3) * 0.30 + pph t3

main = do
   print $ round (pph pkp)

When we no longer use recursive controlled by pkp <= t1. Otherwise, we will have endlees loop.

Guard can control the tail of of recursive.

Now our last issue, calculated value in my country should be in integer, rather than real number.

Integer Value

How do we round it inside function?

We should typecast the taxable income in the first place.

-- taxable income
pkp :: Int
pkp = 10^9

-- income tax using progressive tariff
pph :: Int -> Int
pph pkp = round $ pph_recursive $ fromIntegral pkp
  where
    [t1, t2, t3]  = map (* 10^6) [50, 250, 500]
    pph_recursive pkp_real = pkp_guard pkp_real
    pkp_guard pkp
      | pkp <= t1 = pkp * 0.05
      | pkp <= t2 = (pkp - t1) * 0.15 + pph_rec t1
      | pkp <= t3 = (pkp - t2) * 0.25 + pph_rec t2
      | otherwise = (pkp - t3) * 0.30 + pph_rec t3

main = print $ pph pkp

Notice that we are no longer need to use round in main do clause. And we can even omit do in oneliner fashioned.

Haskell: Progressive Tax Tariff Code

The code is very nice and intuitive.


What is Next ?

How about the challenge above ?

There are other way to do this calculation. Consider continue reading [ Haskell - Tax Tariff - Part Two ].

Thank you for visiting.