I'm facing a problem in Idris, where I want to create a type-level "check" based on a decidable property, where if the property holds I get the type I want, but if the property fails I get Unit
(()
), signaling that the program is in an inconsistent state (and should not compile if I decide to use it as my original type).
Here's an example:
TestType : {k : Nat} -> Nat -> Vect k Nat -> Type
TestType n ls with (isElem n ls)
TestType n ls | Yes _ = Nat
TestType n ls | No _ = ()
mkTestTypeFromNat : (n : Nat) -> (ls : Vect k Nat) -> Elem n ls -> Nat -> TestType {k=k} n ls
mkTestTypeFromNat n ls prf res = res
mkTestTypeFromUnit : (n : Nat) -> (ls : Vect k Nat) -> Not (Elem n ls) -> TestType {k=k} n ls
mkTestTypeFromUnit n ls prf = ()
When I try to compile this, it shows me the following errors:
When checking right hand side of mkTestTypeFromNat:
Type mismatch between
Nat (Type of n)
and
with block in Extensible_Records.TestType n
k
ls
(isElem n ls) (Expected type)
When checking right hand side of mkTestTypeFromUnit:
Type mismatch between
() (Type of ())
and
with block in Extensible_Records.TestType n
k
ls
(isElem n ls) (Expected type)
In each of these mkTestTypeFrom_
functions I provide the proof of the deciable property, either a proof the element is in the list or the proof it isn't. Shouldn't the typechecker realize it has these proofs, and be able to compute the with (isElem n ls)
section without problems, giving me the correct type in each case? Or am I missing something to convince the typechecker of such?