module Type.Data.Num.Unary.Proof (
Nat(..), Pos(..),
natFromPos,
addNat, addPosL, addPosR,
mulNat, mulPos,
) where
import Type.Data.Num.Unary
(Natural, Positive, Succ, switchNat, switchPos, (:+:), (:*:))
data Nat x = Natural x => Nat
data Pos x = Positive x => Pos
succNat :: Nat x -> Nat (Succ x)
succNat Nat = Nat
prevNat :: (Natural x) => Nat (Succ x) -> Nat x
prevNat Nat = Nat
posSucc :: Nat x -> Pos (Succ x)
posSucc Nat = Pos
prevPos :: (Natural x) => Pos (Succ x) -> Nat x
prevPos Pos = Nat
natFromPos :: Pos x -> Nat x
natFromPos Pos = Nat
newtype
AddNatTheorem x y =
AddNatTheorem {
runAddNatTheorem :: Nat x -> Nat y -> Nat (x :+: y)
}
addNat :: Nat x -> Nat y -> Nat (x :+: y)
addNat x0 y0@Nat =
runAddNatTheorem
(switchNat
(AddNatTheorem $ \Nat Nat -> Nat)
(AddNatTheorem $ \x -> succNat . addNat x . prevNat))
x0 y0
newtype
AddPosRTheorem x y =
AddPosRTheorem {
runAddPosRTheorem :: Nat x -> Pos y -> Pos (x :+: y)
}
addPosR :: Nat x -> Pos y -> Pos (x :+: y)
addPosR x0 y0@Pos =
runAddPosRTheorem
(switchPos
(AddPosRTheorem $ \x ->
posSucc . addNat x . prevPos))
x0 y0
newtype
AddPosLTheorem x y =
AddPosLTheorem {
runAddPosLTheorem :: Pos x -> Nat y -> Pos (x :+: y)
}
addPosL :: Pos x -> Nat y -> Pos (x :+: y)
addPosL x0 y0@Nat =
runAddPosLTheorem
(switchNat
(AddPosLTheorem $ \x _y -> x)
(AddPosLTheorem $ \x ->
posSucc . addNat (natFromPos x) . prevNat))
x0 y0
newtype
MulNatTheorem x y =
MulNatTheorem {
runMulNatTheorem :: Nat x -> Nat y -> Nat (x :*: y)
}
mulNat :: Nat x -> Nat y -> Nat (x :*: y)
mulNat x0 y0@Nat =
runMulNatTheorem
(switchNat
(MulNatTheorem $ \Nat Nat -> Nat)
(MulNatTheorem $ \x -> addNat x . mulNat x . prevNat))
x0 y0
newtype
MulPosTheorem x y =
MulPosTheorem {
runMulPosTheorem :: Pos x -> Pos y -> Pos (x :*: y)
}
mulPos :: Pos x -> Pos y -> Pos (x :*: y)
mulPos x0 y0@Pos =
runMulPosTheorem
(switchPos
(MulPosTheorem $ \x ->
addPosL x . mulNat (natFromPos x) . prevPos))
x0 y0