2 -- | Natural numbers inductivey defined at the type-level, and of kind @*@.
3 module Language.Symantic.Typing.Peano where
5 import Data.Type.Equality
7 -- * Types 'Zero' and 'Succ'
11 -- ** Type synonyms for a few numbers
19 -- | Singleton for 'Zero' and 'Succ'.
22 SSucc :: SPeano p -> SPeano (Succ p)
23 instance TestEquality SPeano where
24 testEquality SZero SZero = Just Refl
25 testEquality (SSucc x) (SSucc y)
26 | Just Refl <- testEquality x y
28 testEquality _ _ = Nothing
31 -- | Implicit construction of 'SPeano'.
34 instance IPeano Zero where
36 instance IPeano p => IPeano (Succ p) where
41 EPeano :: SPeano p -> EPeano
42 instance Eq EPeano where
43 EPeano x == EPeano y =
44 case testEquality x y of
47 instance Show EPeano where
48 show (EPeano x) = show (integral_from_peano x::Integer)
50 -- * Interface with 'Integral'
51 integral_from_peano :: Integral i => SPeano p -> i
52 integral_from_peano SZero = 0
53 integral_from_peano (SSucc x) = 1 + integral_from_peano x
55 peano_from_integral :: Integral i => i -> (forall p. SPeano p -> ret) -> ret
56 peano_from_integral 0 k = k SZero
57 peano_from_integral i k | i > 0 =
58 peano_from_integral (i - 1) $ \p -> k (SSucc p)
59 peano_from_integral _ _ = error "peano_from_integral"
62 -- | /Type-level natural number/, inductively defined.
69 SNatS :: SNat n -> SNat ('S n)
70 instance Show (SNat n) where
71 showsPrec _p = showsPrec 10 . intNat
73 intNat :: SNat n -> Int
76 go :: Int -> SNat n -> Int
78 go i (SNatS n) = go (1 + i) n
80 type family (+) (a::Nat) (b::Nat) :: Nat where