recover-rtti-0.3.0.0: src/Debug/RecoverRTTI/Nat.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
-- | Inductive type-level natural numbers
module Debug.RecoverRTTI.Nat (
-- * Type-level natural numbers
Nat(..)
, SNat(..)
, KnownNat(..)
, natVal
-- * Type level functions computing natural numbers
, Length
) where
{-------------------------------------------------------------------------------
Natural numbers
-------------------------------------------------------------------------------}
-- | Natural numbers
--
-- Intended to be used lifted to the type level; unlike @ghc@'s type level
-- natural numbers, these are inductive.
data Nat = Z | S Nat
-- | Singleton for 'Nat'
data SNat (n :: Nat) where
SZ :: SNat 'Z
SS :: SNat n -> SNat ('S n)
class KnownNat (n :: Nat) where
singNat :: SNat n
instance KnownNat 'Z where singNat = SZ
instance KnownNat n => KnownNat ('S n) where singNat = SS singNat
natVal :: forall n proxy. KnownNat n => proxy n -> Int
natVal _ = go (singNat :: SNat n)
where
go :: forall m. SNat m -> Int
go SZ = 0
go (SS n) = go n + 1
{-------------------------------------------------------------------------------
Type-level functions computing natural numbers
-------------------------------------------------------------------------------}
type family Length (xs :: [k]) :: Nat where
Length '[] = 'Z
Length (_ ': xs) = 'S (Length xs)