Consider the following extracted piece of code for proving the "Unicity of Typing" for variable in Agda:
unicity : ∀ {Γ₁ Γ₂ e τ₁ τ₂} → (Γ₁ ⊢ e ∷ τ₁) → (Γ₂ ⊢ e ∷ τ₂) → (Γ₁ ≈ Γ₂) → (τ₁ ∼ τ₂)
unicity (VarT here) (VarT here) (_ , ( τ∼ , _ )) = τ∼
unicity (VarT here) (VarT (ski`p {α = α} lk2)) (s≡s' , ( _ , _ )) = ⊥-elim (toWitnessFalse α (toWitness` s≡s'))
unicity (VarT (skip {α = α} lk1)) (VarT here) (s'≡s , ( _ , _ )) = ⊥-elim (toWitnessFalse α (toWitness s'≡s))
unicity (VarT (skip lk1)) (VarT (skip lk2)) (_ ,( _ , Γ≈ )) = unicity (VarT lk1) (VarT lk2) Γ≈
I need an explanation on the working of ⊥-elim , toWitnessFalse and toWitness. Also, what do the expressions ⊤ and ⊥ mean/stand for?
⊥is the empty type, so (in a total, consistent language) you can never construct a value of type⊥. But this also means that any proposition you can think of, follows from⊥. This is what⊥-elimwitnesses:This is very useful in practice because you might be writing proofs under some assumption, and some of those assumptions might be
⊥, or they might be negative statements (A → ⊥for someA) and you can prove theAas well, etc. Then, what you find out is effectively that you don't have to care about that particular branch anymore, since it is impossible; but then, just because you don't care, you still have to formally satisfy the result type somehow. This is what⊥-elimgives you.toWitness's type and related definitions are as follows:Given a
Q : Dec P,True Qis either⊤(ifQ = yes _) or⊥(ifQ = no _). The only way to calltoWitness, then, is to haveQsay thatPis true and pass the trivial unit constructortt : ⊤; the only other possibility would be to haveQsay thatPis false, and pass as an argument a⊥but as we've seen, that's not possible. In summary,toWitnesssays that ifQtells us the decision thatPholds, then we can get a proof ofPfromQ.toWitnessFalseis exactly the same with the roles reversed: ifQtells us the decision thatPdoesn't hold, then we can get a proof of¬ PfromQ.