The temptation of the challenge is so high. How about last attempt to simplify the code, based on the original calculation method from the first article?

Free Monoid


Rewrite The Guard

Consider going back to our previous nice code, with guard, but reversed order.

import Data.Foldable

-- taxable incomes
pkps :: [Int]
pkps = [0, 50*10^6, 250*10^6, 500*10^6, 10^9]

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

main = forM_ pkps (print . pph)

Code above will show each calculation as below

0
2500000
32500000
95000000
245000000

It is simple, clean, and easy to understand.

Can you see the pattern with that guard above?


Alternate Recursive

Consider using list comprehension, and built the recursive based on pattern above.

import Data.Foldable

-- taxable incomes
pkps :: [Int]
pkps = [0, 50*10^6, 250*10^6, 500*10^6, 10^9]

-- income tax using progressive tariff
pph :: Int -> Int
pph pkp = round $ pph_recursive $ fromIntegral pkp
  where
  pph_recursive 0 = 0
  pph_recursive pkp_real = (pkp_real - tm) * p + pph_recursive(tm)
    where
    -- [(tingkat, persentase)]
    reff    = [(0, 0.05), (50, 0.15), (250, 0.25), (500, 0.30)]
    indices = [ i | (i, (t, p)) <- zip [0..] reff, pkp_real > t * (10^6)]
    (t, p)  = (reff !! last indices)
    tm      = t * (10^6)

main = forM_ pkps (print . pph)

It turned out, that we need nested where clause. And I still need pattern matching to stop the recursion.

Code above will show each result the same as previous output.

It is not simple. And not easy to understand.


Further Attempt

Consider using lambda as our last resort.

import Data.Foldable

-- taxable incomes
pkps :: [Int]
pkps = [0, 50*10^6, 250*10^6, 500*10^6, 10^9]

-- income tax using progressive tariff
pph :: Int -> Int
pph pkp = round $ pph_recursive $ fromIntegral pkp
  where
  -- [(tingkat, persentase)]
  reff    = [(0, 5), (50, 15), (250, 25), (500, 30)]
  tarrifs = [ (t*(10^6), (p/100)) | (t, p) <- reff]
  pph_recursive 0        = 0
  pph_recursive pkp_real = 
    (\(t, p) -> (pkp_real - t) * p + pph_recursive(t)) tariff
    where
    indices = [ i | (i, (t, p)) <- zip [0..] tarrifs, pkp_real > t]
    tariff  = tarrifs !! last indices    

main = mapM_ (print . pph) pkps

Code above will show each result the same as previous output.

It is getting cryptic. And simply garbage. A sad ending in the middle of midnight.


Conclusion

I fail

However, examining this many codes to solve one issue, is good experience anyway. I found that Haskell has a very nice syntax. Thus, I won’t regret this mess.

The first calculation code in this series article is the coolest. Consider continue going back reading [ Haskell - Tax Tariff - Part One ].

Thank you for visiting. We shall meet again. Farewell.