module TypeLevel.Number.Nat (
I
, O
, Z
, Nat(..)
, SomeNat(..)
, withNat
, natT
, nat
, module TypeLevel.Number.Classes
) where
import Data.Word (Word8,Word16,Word32,Word64)
import Data.Int (Int8, Int16, Int32, Int64 )
import Data.Typeable (Typeable)
import TypeLevel.Number.Classes
import TypeLevel.Number.Nat.Types
import TypeLevel.Number.Nat.TH
import TypeLevel.Reify
class Nat n where
toInt :: Integral i => n -> i
class Pos n
instance Nat Z where toInt _ = 0
instance Nat (I Z) where toInt _ = 1
instance Nat (O n) => Nat (O (O n)) where toInt _ = 0 + 2 * toInt (undefined :: (O n))
instance Nat (O n) => Nat (I (O n)) where toInt _ = 1 + 2 * toInt (undefined :: (O n))
instance Nat (I n) => Nat (O (I n)) where toInt _ = 0 + 2 * toInt (undefined :: (I n))
instance Nat (I n) => Nat (I (I n)) where toInt _ = 1 + 2 * toInt (undefined :: (I n))
class Number_Is_Denormalized a
instance (Number_Is_Denormalized Z) => Nat (O Z) where
toInt = error "quench warning"
instance (Nat n, Positive n) => Pos n
data SomeNat where
SomeNat :: Nat n => n -> SomeNat
deriving Typeable
instance Show SomeNat where
showsPrec d (SomeNat n) = showParen (d > 10) $
showString "withNat SomeNat " . shows (toInt n :: Integer)
withNat :: forall i a. (Integral i) => (forall n. Nat n => n -> a) -> i -> a
withNat f i0
| i0 < 0 = error "TypeLevel.Number.Nat.withNat: negative number"
| i0 == 0 = f (undefined :: Z)
| otherwise = cont (fromIntegral i0) f f
where
cont :: Integer -> (forall n m. (Nat n, n ~ O m) => n -> a)
-> (forall n m. (Nat n, n ~ I m) => n -> a) -> a
cont 1 _ k1 = k1 (undefined :: I Z)
cont i k0 k1 = cont (i `quot` 2) k0' k1'
where
k0' :: forall n m. (Nat n, n ~ O m) => n -> a
k0' _ | odd i = k1 (undefined :: I n)
| otherwise = k0 (undefined :: O n)
k1' :: forall n m. (Nat n, n ~ I m) => n -> a
k1' _ | odd i = k1 (undefined :: I n)
| otherwise = k0 (undefined :: O n)
instance Reify Z Integer where witness = Witness 0
instance (Nat (O n)) => Reify (O n) Integer where witness = Witness $ toInt (undefined :: O n)
instance (Nat (I n)) => Reify (I n) Integer where witness = Witness $ toInt (undefined :: I n)
instance Reify Z Int where witness = Witness 0
instance (Nat (O n)) => Reify (O n) Int where witness = Witness $ toInt (undefined :: O n)
instance (Nat (I n)) => Reify (I n) Int where witness = Witness $ toInt (undefined :: I n)
instance Reify Z Word8 where witness = Witness 0
instance (Nat (O n), (O n) `Lesser` $(natT 0x100)) => Reify (O n) Word8 where witness = Witness $ toInt (undefined :: O n)
instance (Nat (I n), (I n) `Lesser` $(natT 0x100)) => Reify (I n) Word8 where witness = Witness $ toInt (undefined :: I n)
instance Reify Z Word16 where witness = Witness 0
instance (Nat (O n), (O n) `Lesser` $(natT 0x10000)) => Reify (O n) Word16 where witness = Witness $ toInt (undefined :: O n)
instance (Nat (I n), (I n) `Lesser` $(natT 0x10000)) => Reify (I n) Word16 where witness = Witness $ toInt (undefined :: I n)
instance Reify Z Word32 where witness = Witness 0
instance (Nat (O n)) => Reify (O n) Word32 where witness = Witness $ toInt (undefined :: O n)
instance (Nat (I n)) => Reify (I n) Word32 where witness = Witness $ toInt (undefined :: I n)
instance Reify Z Word64 where witness = Witness 0
instance (Nat (O n)) => Reify (O n) Word64 where witness = Witness $ toInt (undefined :: O n)
instance (Nat (I n)) => Reify (I n) Word64 where witness = Witness $ toInt (undefined :: I n)
instance Reify Z Int8 where witness = Witness 0
instance (Nat (O n), (O n) `Lesser` $(natT 0x80)) => Reify (O n) Int8 where witness = Witness $ toInt (undefined :: O n)
instance (Nat (I n), (I n) `Lesser` $(natT 0x80)) => Reify (I n) Int8 where witness = Witness $ toInt (undefined :: I n)
instance Reify Z Int16 where witness = Witness 0
instance (Nat (O n), (O n) `Lesser` $(natT 0x8000)) => Reify (O n) Int16 where witness = Witness $ toInt (undefined :: O n)
instance (Nat (I n), (I n) `Lesser` $(natT 0x8000)) => Reify (I n) Int16 where witness = Witness $ toInt (undefined :: I n)
instance Reify Z Int32 where witness = Witness 0
instance (Nat (O n)) => Reify (O n) Int32 where witness = Witness $ toInt (undefined :: O n)
instance (Nat (I n)) => Reify (I n) Int32 where witness = Witness $ toInt (undefined :: I n)
instance Reify Z Int64 where witness = Witness 0
instance (Nat (O n)) => Reify (O n) Int64 where witness = Witness $ toInt (undefined :: O n)
instance (Nat (I n)) => Reify (I n) Int64 where witness = Witness $ toInt (undefined :: I n)
type family Add0Bit n :: *
type instance Add0Bit Z = Z
type instance Add0Bit (O n) = (O (O n))
type instance Add0Bit (I n) = (O (I n))
type instance Normalized Z = Z
type instance Normalized (I n) = I (Normalized n)
type instance Normalized (O n) = Add0Bit (Normalized n)
instance Show Z where show _ = "[0:N]"
instance Nat (O n) => Show (O n) where show n = "["++show (toInt n :: Integer)++":N]"
instance Nat (I n) => Show (I n) where show n = "["++show (toInt n :: Integer)++":N]"
type instance Next Z = I Z
type instance Next (I n) = O (Next n)
type instance Next (O n) = I n
type instance Prev (I Z) = Z
type instance Prev (O (O n)) = I (Prev (O n))
type instance Prev (I (O n)) = O (O n)
type instance Prev (O (I n)) = I (Prev (I n))
type instance Prev (I (I n)) = O (I n)
type family Join a b :: *
type instance Join IsLesser IsEqual = IsLesser
type instance Join IsEqual IsEqual = IsEqual
type instance Join IsGreater IsEqual = IsGreater
type instance Join a IsLesser = IsLesser
type instance Join a IsGreater = IsGreater
type instance Compare Z Z = IsEqual
type instance Compare (O n) Z = IsGreater
type instance Compare (I n) Z = IsGreater
type instance Compare Z (O n) = IsLesser
type instance Compare Z (I n) = IsLesser
type instance Compare (O n) (O m) = Compare n m
type instance Compare (O n) (I m) = Join IsLesser (Compare n m)
type instance Compare (I n) (O m) = Join IsGreater (Compare n m)
type instance Compare (I n) (I m) = Compare n m
instance Nat (I n) => Positive (I n)
instance Nat (O n) => Positive (O n)
instance Nat (I n) => NonZero (I n)
instance Nat (O n) => NonZero (O n)
data Carry
data NoCarry
type family Add' n m c :: *
type instance Add' Z Z NoCarry = Z
type instance Add' (O n) Z NoCarry = O n
type instance Add' (I n) Z NoCarry = I n
type instance Add' Z (O n) NoCarry = O n
type instance Add' Z (I n) NoCarry = I n
type instance Add' Z Z Carry = I Z
type instance Add' (O n) Z Carry = I n
type instance Add' (I n) Z Carry = Add' (I n) (I Z) NoCarry
type instance Add' Z (O n) Carry = I n
type instance Add' Z (I n) Carry = Add' (I n) (I Z) NoCarry
type instance Add' (O n) (O m) NoCarry = O (Add' n m NoCarry)
type instance Add' (I n) (O m) NoCarry = I (Add' n m NoCarry)
type instance Add' (O n) (I m) NoCarry = I (Add' n m NoCarry)
type instance Add' (I n) (I m) NoCarry = O (Add' n m Carry)
type instance Add' (O n) (O m) Carry = I (Add' n m NoCarry)
type instance Add' (I n) (O m) Carry = O (Add' n m Carry)
type instance Add' (O n) (I m) Carry = O (Add' n m Carry)
type instance Add' (I n) (I m) Carry = I (Add' n m Carry)
type instance Add (O n) (O m) = Normalized (Add' (O n) (O m) NoCarry)
type instance Add (I n) (O m) = Normalized (Add' (I n) (O m) NoCarry)
type instance Add (O n) (I m) = Normalized (Add' (O n) (I m) NoCarry)
type instance Add (I n) (I m) = Normalized (Add' (I n) (I m) NoCarry)
type instance Add (O n) Z = Normalized (Add' (O n) Z NoCarry)
type instance Add (I n) Z = Normalized (Add' (I n) Z NoCarry)
type instance Add Z (O n) = Normalized (Add' Z (O n) NoCarry)
type instance Add Z (I n) = Normalized (Add' Z (I n) NoCarry)
type instance Add Z Z = Normalized (Add' Z Z NoCarry)
data Borrow
data NoBorrow
type family Sub' n m c :: *
type instance Sub' Z Z NoBorrow = Z
type instance Sub' (O n) Z NoBorrow = O n
type instance Sub' (I n) Z NoBorrow = I n
type instance Sub' (O n) Z Borrow = I (Sub' n Z Borrow)
type instance Sub' (I n) Z Borrow = O n
type instance Sub' (O n) (O m) NoBorrow = O (Sub' n m NoBorrow)
type instance Sub' (I n) (O m) NoBorrow = I (Sub' n m NoBorrow)
type instance Sub' (O n) (I m) NoBorrow = I (Sub' n m Borrow)
type instance Sub' (I n) (I m) NoBorrow = O (Sub' n m NoBorrow)
type instance Sub' (O n) (O m) Borrow = I (Sub' n m Borrow)
type instance Sub' (I n) (O m) Borrow = O (Sub' n m NoBorrow)
type instance Sub' (O n) (I m) Borrow = O (Sub' n m Borrow)
type instance Sub' (I n) (I m) Borrow = I (Sub' n m Borrow)
type instance Sub (O n) (O m) = Normalized (Sub' (O n) (O m) NoBorrow)
type instance Sub (I n) (O m) = Normalized (Sub' (I n) (O m) NoBorrow)
type instance Sub (O n) (I m) = Normalized (Sub' (O n) (I m) NoBorrow)
type instance Sub (I n) (I m) = Normalized (Sub' (I n) (I m) NoBorrow)
type instance Sub (O n) Z = Normalized (Sub' (O n) Z NoBorrow)
type instance Sub (I n) Z = Normalized (Sub' (I n) Z NoBorrow)
type instance Sub Z Z = Normalized (Sub' Z Z NoBorrow)
type instance Mul n Z = Z
type instance Mul n (O m) = Normalized (O (Mul n m))
type instance Mul n (I m) = Normalized (Add' n (O (Mul n m)) NoCarry)