module Language.Symantic.Typing.Peano where
import Data.Type.Equality
data Zero
data Succ p
type P0 = Zero
type P1 = Succ P0
type P2 = Succ P1
type P3 = Succ P2
data SPeano p where
SZero :: SPeano Zero
SSucc :: SPeano p -> SPeano (Succ p)
instance TestEquality SPeano where
testEquality SZero SZero = Just Refl
testEquality (SSucc x) (SSucc y)
| Just Refl <- testEquality x y
= Just Refl
testEquality _ _ = Nothing
class IPeano p where
ipeano :: SPeano p
instance IPeano Zero where
ipeano = SZero
instance IPeano p => IPeano (Succ p) where
ipeano = SSucc ipeano
data EPeano where
EPeano :: SPeano p -> EPeano
instance Eq EPeano where
EPeano x == EPeano y =
case testEquality x y of
Just _ -> True
_ -> False
instance Show EPeano where
show (EPeano x) = show (integral_from_peano x::Integer)
integral_from_peano :: Integral i => SPeano p -> i
integral_from_peano SZero = 0
integral_from_peano (SSucc x) = 1 + integral_from_peano x
peano_from_integral :: Integral i => i -> (forall p. SPeano p -> ret) -> ret
peano_from_integral 0 k = k SZero
peano_from_integral i k | i > 0 =
peano_from_integral (i 1) $ \p -> k (SSucc p)
peano_from_integral _ _ = error "peano_from_integral"