{-# LANGUAGE DataKinds, GADTs, TypeFamilies, TypeOperators,
ConstraintKinds, ScopedTypeVariables, RankNTypes #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveDataTypeable#-}
{-# LANGUAGE CPP #-}
module Numerical.Nat(Nat(..),N0,N1,N2,N3,N4,N5,N6,N7,N8,N9,N10
,SNat(..), type (+),plus_id_r,plus_succ_r,gcastWith,Proxy(..),LitNat,U) where
import Data.Typeable
import Data.Data
import qualified GHC.TypeLits as TL
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707
import Data.Type.Equality(gcastWith)
#else
import Data.Proxy
#endif
type LitNat = TL.Nat
data Nat = S !Nat | Z
deriving (Eq,Show,Read,Typeable,Data)
#if defined(__GLASGOW_HASKELL__) && ( __GLASGOW_HASKELL__ >= 707) && ( __GLASGOW_HASKELL__ < 709)
deriving instance Typeable 'Z
deriving instance Typeable 'S
#endif
type family U (n:: TL.Nat) :: Nat where
U 0 = 'Z
U n = 'S (U (((TL.-)) n 1))
type family n1 + n2 where
'Z + n2 = n2
('S n1') + n2 = 'S (n1' + n2)
data SNat :: Nat -> * where
SZero :: SNat 'Z
SSucc :: SNat n -> SNat ('S n)
plus_id_r :: SNat n -> ((n + 'Z) :~: n)
plus_id_r SZero = Refl
plus_id_r (SSucc n) = gcastWith (plus_id_r n) Refl
plus_succ_r :: SNat n1 -> Proxy n2 -> ((n1 + ('S n2)) :~: ('S (n1 + n2)))
plus_succ_r SZero _ = Refl
plus_succ_r (SSucc n1) proxy_n2 = gcastWith (plus_succ_r n1 proxy_n2) Refl
type N0 = 'Z
type N1 = 'S N0
type N2 = 'S N1
type N3 = 'S N2
type N4 = 'S N3
type N5 = 'S N4
type N6 = 'S N5
type N7 = 'S N6
type N8 = 'S N7
type N9 = 'S N8
type N10 = 'S N9