witness-0.5: src/Data/Witness/Nat.hs
module Data.Witness.Nat where
import Data.Constraint (Dict(..))
import Data.Maybe
import Data.Nat
import Data.Type.Equality
import Data.Witness.Representative
import Prelude hiding ((.), id)
data NatType (t :: Nat) where
ZeroType :: NatType 'Zero
SuccType :: NatType t -> NatType ('Succ t)
instance TestEquality NatType where
testEquality ZeroType ZeroType = return Refl
testEquality (SuccType a) (SuccType b) = do
Refl <- testEquality a b
return Refl
testEquality _ _ = Nothing
instance Representative NatType where
getRepWitness ZeroType = Dict
getRepWitness (SuccType n) =
case getRepWitness n of
Dict -> Dict
instance Is NatType 'Zero where
representative = ZeroType
instance (Is NatType n) => Is NatType ('Succ n) where
representative = SuccType representative
data GreaterEqual (a :: Nat) (b :: Nat) where
ZeroGreaterEqual :: GreaterEqual a 'Zero
SuccGreaterEqual :: GreaterEqual a b -> GreaterEqual ('Succ a) ('Succ b)
sameGreaterEqualWit :: NatType a -> GreaterEqual a a
sameGreaterEqualWit ZeroType = ZeroGreaterEqual
sameGreaterEqualWit (SuccType a) = SuccGreaterEqual $ sameGreaterEqualWit a
diff1GreaterEqualWit :: GreaterEqual a b -> GreaterEqual ('Succ a) b
diff1GreaterEqualWit ZeroGreaterEqual = ZeroGreaterEqual
diff1GreaterEqualWit (SuccGreaterEqual ge) = SuccGreaterEqual $ diff1GreaterEqualWit ge
natGreaterEqual :: NatType a -> NatType b -> Maybe (GreaterEqual a b)
natGreaterEqual _ ZeroType = return ZeroGreaterEqual
natGreaterEqual ZeroType _ = Nothing
natGreaterEqual (SuccType a) (SuccType b) = do
al <- natGreaterEqual a b
return $ SuccGreaterEqual al
type family Add (a :: Nat) (b :: Nat) :: Nat where
Add 'Zero b = b
Add ('Succ a) b = 'Succ (Add a b)
addWit :: NatType a -> NatType b -> NatType (Add a b)
addWit ZeroType b = b
addWit (SuccType a) b = SuccType $ addWit a b
addZeroWit :: NatType a -> Add a 'Zero :~: a
addZeroWit ZeroType = Refl
addZeroWit (SuccType a) =
case addZeroWit a of
Refl -> Refl
succAddWit' :: forall a b. NatType a -> 'Succ (Add a b) :~: Add a ('Succ b)
succAddWit' ZeroType = Refl
succAddWit' (SuccType a) =
case succAddWit' @_ @b a of
Refl -> Refl
succAddWit :: forall a b. NatType a -> NatType b -> 'Succ (Add a b) :~: Add a ('Succ b)
succAddWit a _ = succAddWit' @a @b a
addGreaterEqualWit :: NatType a -> NatType b -> GreaterEqual (Add a b) a
addGreaterEqualWit a ZeroType =
case addZeroWit a of
Refl -> sameGreaterEqualWit a
addGreaterEqualWit a (SuccType b) =
case succAddWit a b of
Refl -> diff1GreaterEqualWit $ addGreaterEqualWit a b