packages feed

canadian-income-tax-2023.0: src/Tax/Util.hs

-- | Shared utility functions used by other modules
module Tax.Util where

import Data.Fixed (Centi)
import Data.List.NonEmpty (nonEmpty)
import Data.Maybe (fromMaybe, mapMaybe)

-- | Repeatedly apply the function to the argument until it reaches the fixed point.
fixEq :: Eq a => (a -> a) -> a -> a
fixEq f a
   | a == a' = a
   | otherwise = fixEq f a'
   where a' = f a

-- | Sum the list of arguments; return 'Nothing' iff all items are 'Nothing'.
totalOf :: Num a => [Maybe a] -> Maybe a
totalOf = fmap sum . nonEmpty . mapMaybe id

-- | Subtraction under 'Maybe'
difference :: Maybe Centi -> Maybe Centi -> Maybe Centi
difference Nothing Nothing = Nothing
difference a b = Just (fromMaybe 0 a - fromMaybe 0 b)

-- | Non-negative subtraction under 'Maybe', returning @Just 0@ instead of negative results
nonNegativeDifference :: Maybe Centi -> Maybe Centi -> Maybe Centi
nonNegativeDifference Nothing Nothing = Nothing
nonNegativeDifference a b = Just (max 0 $ fromMaybe 0 a - fromMaybe 0 b)

-- | Multiplication under 'Maybe'
fractionOf :: Maybe Rational -> Maybe Centi -> Maybe Centi
fractionOf (Just x) (Just amt) = Just $ fromRational (x * toRational amt)
fractionOf _ _ = Nothing