{-# LANGUAGE DataKinds #-}

-- | Provides type level fractions based on type nats
module Data.Params.Frac
    ( Frac (..)
    , KnownFrac (..)
    , fracVal
    )
    where

import GHC.TypeLits
import Data.Proxy

-- | (Kind) This is the kind of type-level fractions.  
-- It is not built in to GHC, but instead defined in terms of 'Nat'
data Frac = (/) Nat Nat

-- | This class gives the 'Rational' associated with a type-level fraction.
class KnownFrac (n :: Frac) where
    fracSing :: SFrac n 

instance (KnownNat a, KnownNat b) => KnownFrac (a/b) where
    fracSing = SFrac 
        (fromIntegral $ natVal (Proxy::Proxy a)) 
        (fromIntegral $ natVal (Proxy::Proxy b))

-- | get the value from a type frac
-- fracVal :: forall n proxy. (KnownFrac n) => proxy n -> Rational
fracVal :: forall f n proxy. (KnownFrac n, Fractional f) => proxy n -> f 
fracVal _ = case fracSing :: SFrac n of
    SFrac a b -> fromIntegral a / fromIntegral b 

data SFrac (n :: Frac) = SFrac 
    {-#UNPACK#-}!Int
    {-#UNPACK#-}!Int
-- data SFrac (n :: Frac) = SFrac Integer Integer