{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Data.Tax.ATO.Days
( Days
, days
, daysAll
, daysNone
, getDays
, getFraction
, DaysInYear
)
where
import GHC.TypeLits
import Data.Proxy
import Data.Ratio ((%))
import Data.Time.Calendar (isLeapYear)
type Year = Nat
type DaysInYear = KnownNat
daysInYear :: KnownNat n => Proxy n -> Integer
daysInYear :: forall (n :: Nat). KnownNat n => Proxy n -> Integer
daysInYear Proxy n
proxy = case Integer -> Bool
isLeapYear (forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal Proxy n
proxy) of
Bool
False -> Integer
365
Bool
True -> Integer
366
newtype Days (n :: Year) = Days
{ forall (n :: Nat). Days n -> Integer
getDays :: Integer
}
deriving (Int -> Days n -> ShowS
forall (n :: Nat). Int -> Days n -> ShowS
forall (n :: Nat). [Days n] -> ShowS
forall (n :: Nat). Days n -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Days n] -> ShowS
$cshowList :: forall (n :: Nat). [Days n] -> ShowS
show :: Days n -> String
$cshow :: forall (n :: Nat). Days n -> String
showsPrec :: Int -> Days n -> ShowS
$cshowsPrec :: forall (n :: Nat). Int -> Days n -> ShowS
Show)
days :: forall a. (DaysInYear a) => Integer -> Days a
days :: forall (a :: Nat). DaysInYear a => Integer -> Days a
days = forall (n :: Nat). Integer -> Days n
Days forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => a -> a -> a
max Integer
0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => a -> a -> a
min (forall (n :: Nat). KnownNat n => Proxy n -> Integer
daysInYear (forall {k} (t :: k). Proxy t
Proxy :: Proxy a))
daysAll :: forall a. (DaysInYear a) => Days a
daysAll :: forall (a :: Nat). DaysInYear a => Days a
daysAll = forall (n :: Nat). Integer -> Days n
Days (forall (n :: Nat). KnownNat n => Proxy n -> Integer
daysInYear (forall {k} (t :: k). Proxy t
Proxy :: Proxy a))
daysNone :: Days a
daysNone :: forall (a :: Nat). Days a
daysNone = forall (n :: Nat). Integer -> Days n
Days Integer
0
getFraction :: forall a frac. (DaysInYear a, Fractional frac) => Days a -> frac
getFraction :: forall (a :: Nat) frac.
(DaysInYear a, Fractional frac) =>
Days a -> frac
getFraction Days a
n = forall a. Fractional a => Rational -> a
fromRational forall a b. (a -> b) -> a -> b
$ forall (n :: Nat). Days n -> Integer
getDays Days a
n forall a. Integral a => a -> a -> Ratio a
% forall (n :: Nat). KnownNat n => Proxy n -> Integer
daysInYear (forall {k} (t :: k). Proxy t
Proxy :: Proxy a)