I've been learning Agda recently and I've been making a lot of progress but I'm stuck on one thing: proving that a type is NOT inhabited.
I have a relation on Bool
s defined as follows:
data Test : Rel Bool 0ℓ where
direct : Test false true
indirect : {j0 j1 j2 : Bool} → Test j0 j1 → Test j1 j2 → Test j0 j2
The direct
constructor defined some of the relation, while the indirect
constructor adds the transitive closure. Obviously in this example the transitive closure adds nothing, but in the actual problem I'm working on it's important.
I would like to prove testNot : ¬ Test true false
but I can't work out how.
My feeling is that the type checker is smart enough to know that the direct
constructor isn't useful, and in the indirect
constructor j0
is obviously true
and j2
is obviously false
. This leaves only the two possible cases for j1
to consider. The code I tried was:
testNot (indirect {true} {false} {false} () _)
testNot (indirect {true} {true} {false} _ ())
I thought that the type checker would know that the only thing that can go in either of those absurd patterns is one of those two indirect
constructors with the same arguments, leading to an infinite chain of constructors which is disallowed, hence the absurd patterns. This didn't work -- the error I get is
Test true false should be empty, but the following constructor
patterns are valid:
indirect {._} {_} {._} _ _
when checking the clause left hand side
testNot (indirect {true} {false} {false} () _)
So I guess I need to prove this by induction on the depth of constructors: fist prove that direct
does not have type Test true false
, then prove that if no "shallower" constructors have this type then no "deeper" constructor can either and the theorem follows from induction. The problem is I don't know how to express this. What do you suggest?
I would start by proving a positive statement about the value the
Test
indices take:
open import Relation.Nullary
open import Data.Product
open import Relation.Binary.PropositionalEquality
open import Function.Base
test-indices : ∀ {i j} → Test i j → (i ≡ false × j ≡ true)
test-indices direct = refl , refl
test-indices (indirect p q) =
let (_ , eq₁) = test-indices p in
let (eq₂ , _) = test-indices q in
let absurd = trans (sym eq₁) eq₂ in
case absurd of λ where ()
Your result is then a direct corollary:
testNot : ¬ (Test true false)
testNot p = case proj₁ (test-indices p) of λ where ()