Say I have a data type
data Interval :: Nat -> Nat -> * where
Go :: Interval m n -> Interval m (S n)
Empty :: SNat n -> Interval n n
These are half-(right-)open intervals. Nat
are the standard inductive naturals, SNat
are the corresponding singletons.
Now I'd like to get a singleton Nat
for the length of a given interval:
intervalLength :: Interval n (Plus len n) -> SNat len
intervalLength Empty = Z
intervalLength (Go i) = S (intervalLength i)
This does not work, as the Plus
function is not injective. I could probably define it like
intervalLength :: Interval m n -> SNat (Minus n m)
but that would require some lemmas (and additional constraints), I guess. Also, my intervals arise in the former shape.
Background: I tried to do this in Omega and it did not work (omega bug I filed)
Also how could these problems be cracked with modified typecheckers? Can the RHS of the supply the crucial hint to LHS pattern's type equation so that the non-injectiveness cancels out?
How do Agda programmers tackle these problems?