Learn and Discover Open Source with Daily Genuine Experience. From Coding, Front End, Back End, Database, and Static Site Generator.
04

## Haskell - Tax Tariff - Part Four

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? ### 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.