Proving a Type is Uninhabited in Agda - agda

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 Bools 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 ()

Related

How to recover intermediate computation results from a function using "with"?

I wrote a function on the natural numbers that uses the operator _<?_ with the with-abstraction.
open import Data.Maybe
open import Data.Nat
open import Data.Nat.Properties
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
fun : ℕ → ℕ → Maybe ℕ
fun x y with x <? y
... | yes _ = nothing
... | no _ = just y
I would like to prove that if the result of computing with fun is nothing then the original two values (x and y) fulfill x < y.
So far all my attempts fall short to prove the property:
prop : ∀ (x y)
→ fun x y ≡ nothing
→ x < y
prop x y with fun x y
... | just _ = λ()
... | nothing = λ{refl → ?} -- from-yes (x <? y)}
-- This fails because the pattern matching is incomplete,
-- but it shouldn't. There are no other cases
prop' : ∀ (x y)
→ fun x y ≡ nothing
→ x < y
prop' x y with fun x y | x <? y
... | nothing | yes x<y = λ{refl → x<y}
... | just _ | no _ = λ()
--... | _ | _ = ?
In general, I've found that working with the with-abstraction is painful. It is probably due to the fact that with and | hide some magic in the background. I would like to understand what with and | really do, but the "Technical details" currently escape my understanding. Do you know where to look for to understand how to interpret them?
Concrete solution
You need to case-split on the same element on which you case-split in your function:
prop : ∀ x y → fun x y ≡ nothing → x < y
prop x y _ with x <? y
... | yes p = p
In the older versions of Agda, you would have had to write the following:
prop-old : ∀ x y → fun x y ≡ nothing → x < y
prop-old x y _ with x <? y
prop-old _ _ refl | yes p = p
prop-old _ _ () | no _
But now you are able to completely omit a case when it leads to a direct contradiction, which is, in this case, that nothing and just smth can never be equal.
Detailed explanation
To understand how with works you first need to understand how definitional equality is used in Agda to reduce goals. Definitional equality binds a function call with its associated expression depending on the structure of its input. In Agda, this is easily seen by the use of the equal sign in the definition of the different cases of a function (although since Agda builds a tree of cases some definitional equalities might not hold in some cases, but let's forget this for now).
Let us consider the following definition of the addition over naturals:
_+_ : ℕ → ℕ → ℕ
zero + b = b
(suc a) + b = suc (a + b)
This definition provides two definitional equalities that bind zero + b with b and (suc a) + b with suc (a + b). The good thing with definitional equalities (as opposed to propositional equalities) is that Agda automatically uses them to reduce goals whenever possible. This means that, for instance, if in a further goal you have the element zero + p for any p then Agda will automatically reduce it to p.
To allow Agda to do such reduction, which is fundamental in most cases, Agda needs to know which of these two equalities can be exploited, which means a case-split on the first argument of this addition has to be made in any further proof about addition for a reduction to be possible. (Except for composite proofs based on other proofs which use such case-splits).
When using with you basically add additional definitional equalities depending on the structure of the additional element. This only makes sense, understanding that, that you need to case-split on said element when doing proofs about such a function, in order for Agda once again to be able to make use of these definitional equalities.
Let us take your example and apply this reasoning to it, first without the recent ability to omit impossible cases. You need to prove the following statement:
prop-old : ∀ x y → fun x y ≡ nothing → x < y
Introducing parameters in the context, you write the following line:
prop-old x y p = ?
Having written that line, you need to provide a proof of x < y with the elements in the context. x and y are just natural so you expect p to hold enough information for this result to be provable. But, in this case, p is just of type fun x y ≡ nothing which does not give you enough information. However, this type contains a call to function fun so there is hope ! Looking at the definition of fun, we can see that it yields two definitional equalities, which depend on the structure of x <? y. This means that adding this parameter to the proof by using with once more will allow Agda to make use of these equalities. This leads to the following code:
prop-old : ∀ x y → fun x y ≡ nothing → x < y
prop-old x y p with x <? y
prop-old _ _ p | yes q = ?
prop-old _ _ p | no q = ?
At that point, not only did Agda case-split on x <? y, but it also reduced the goal because it is able, in both cases, to use a specific definitional equality of fun. Let us take a closer look at both cases:
In the yes q case, p is now of type nothing ≡ nothing and q is of type x < y which is exactly what you want to prove, which means the goal is simply solved by:
prop-old _ _ p | yes q = q
I the no q case, something more interesting happens, which is somewhat harder to understand. After reduction, p is now of type just y ≡ nothing because Agda could use the second definitional equality of fun. Since _≡_ is a data type, it is possible to case-split on p which basically asks Agda: "Look at this data type and give me all the possible constructors for an element of type just y ≡ nothing". At first, Agda only finds one possible constructor, refl, but this constructor only builds an element of a type where both sides of the equality are the same, which is not the case here by definition because just and nothing are two distinct constructors from the same data type, Maybe. Agda then concludes that there are no possible constructors that could ever build an element of such type, hence this case is actually not possible, which leads to Agda replacing p with the empty pattern () and dismissing this case. This line is thus simply:
prop-old _ _ () | no _
In the more recent versions of Agda, as I explained earlier, some of these steps are done directly by Agda which allows us to directly omit impossible cases when the emptiness of a pattern can be deduced behind the curtain, which leads to the prettier:
prop : ∀ x y → fun x y ≡ nothing → x < y
prop x y _ with x <? y
... | yes p = p
But it is the same process, just done a bit more automatically. Hopefully, these elements will be of some use in your journey towards understanding Agda.

What are the drawbacks of encoding properties using functions?

In Agda, it seems that often there are two ways to refine a set. One is by simply writing a function that checks if a property holds, and lift. For example:
has_true : List Bool -> Bool
has_true (true ∷ xs) = true
has_true (false ∷ xs) = has_true xs
has_true [] = false
Truthy : List Bool -> Set
Truthy list = T (has_true list)
Here, Truthy list is a proof that a boolean list has at least one true element. The other way is by encoding that property directly, as an inductive type:
data Truthy : List Bool -> Set where
Here : (x : Bool) -> (x ≡ true) -> (xs : List Bool) -> Truthy (x ∷ xs)
There : (x : Bool) -> (xs : List Bool) -> Truthy xs -> Truthy (x ∷ xs)
Here, Truthy list also proves the same thing.
I believe I have read a comparison before, but I don't remember. Is there a name for those different styles? What are the advantages and drawbacks of using one style over another? And is there a third option?
So far you listed two ways of defining predicates:
A -> Bool functions.
Inductive predicates.
I would add one more:
A -> Set functions. Could be also called "recursively defined", or "defined by large elimination".
The third version is the following in Agda:
open import Data.Bool
open import Data.Unit
open import Data.Empty
open import Data.List
hastrue : List Bool → Set
hastrue [] = ⊥ -- empty type
hastrue (false ∷ bs) = hastrue bs
hastrue (true ∷ bs) = ⊤ -- unit type
First, let's talk about what kind of predicates are representable using the three options. Here's an ASCII table. * is a wildcard standing for yes/no.
| P : A -> Set | P : A -> Bool | data P : A -> Set |
|-------------------|--------------|---------------|-------------------|
| Proof irrelevant | * | yes | * |
| Structural | yes | yes | * |
| Strictly positive | * | N/A | yes |
| Decidable | * | yes | * |
Proof irrelevance means that all proofs for P x are equal. In the Bool case, a proof is usually some p : P x ≡ true, or p : IsTrue (P x) with IsTrue = λ b → if b then ⊤ else ⊥, and in both cases all proofs are equal indeed. We may or may not want predicates to be irrelevant.
Structural means that P x can only be defined using elements of A which are structurally smaller than x. Functions are always structural, so if some predicate isn't, then it can only be defined inductively.
Strictly positive means that P cannot occur recursively to the left of a function arrow. Non-strictly positive predicates are not definable inductively. An example for a proof-relevant non-strictly positive predicate is the interpretation of codes of function types:
data Ty : Set where
top : Ty
fun : Ty → Ty → Ty
⟦_⟧ : Ty → Set
⟦ top ⟧ = ⊤
⟦ fun A B ⟧ = ⟦ A ⟧ → ⟦ B ⟧ -- you can't put this in "data"
Decidable is self-explanatory; A -> Bool functions are necessarily decidable, which makes them unsuitable for predicates which are undecidable or cannot be easily written out as a structural Bool function. The advantage of decidability is excluded middle reasoning, which is not possible with the non-Bool predicate definitions without postulates or additional decidability proofs.
Second, about the practical ramifications in Agda/Idris.
You can do dependent pattern matching on proofs of inductive predicates. With recursive and Boolean predicates, you have to pattern match on the A values first, to make predicate witnesses compute. Sometimes this makes inductive predicates convenient, e.g. you could have an enumeration type with 10 constructors, and you want a predicate to hold at only one constructor. The inductively defined predicate lets you only match on the true case, while the other versions require you to match on all cases all the time.
On the other hand, Boolean and recursive predicates compute automatically as soon as you know that an A element has a given shape. This can be used in Agda to make type inference fill in proofs automatically, without tactics or instances. For example, a hole or implicit argument with type hastrue xs can be solved by eta rules for pairs and the unit type, whenever xs is a list expression with a known true-containing prefix. This works analogously with Boolean predicates.

Understanding unquoteDecl in Agda

I'm trying to understand Agda's built in reflection mechanisms, so I decided to write a simple function that takes a string for an identifier,
a quoted type, and a quoted term, and simply defines a term of the given type with the given string identifier. Thus, I wrote the following:
testDefineName' : String → TC Type → TC Term → TC ⊤
testDefineName' s t a =
bindTC (freshName s)
(λ n → bindTC t
(λ t' → bindTC a
(λ a' → (bindTC (declareDef (arg (arg-info visible relevant) n) t')
(λ _ → defineFun n ((clause [] a') ∷ []))))))
unquoteDecl = (testDefineName' "test" (quoteTC ℕ) (quoteTC zero))
This type-checks, but, when I try to use "test" elsewhere I get a Not in scope: test error.
The documentation for unquoteDecl is kind of opaque. Appaently declarations should be of the form
unquoteDecl x_1 x_2 ... x_n = m
where the x_i are Names, and m has type TC \top, so maybe what I was trying to do isn't actually possible, but I still don't understand how this mechanism works: if m has to be of type TC ⊤, and thus cannot be a function of the names x_1 x_2 ... x_n, I don't see how it is possible to bring any new names into scope using unquoteDecl at all!
So, to sum up:
Is it possible to define a function like mine using Agda's reflection mechanism so that I can bring new names into scope using a String argument? What I want is something like:
<boilerplate code for unquoting> testDefineName' "test" (quoteTC ℕ) (quoteTC zero)
test' : ℕ
test' = test
to compile (i.e. I can actually use the new name, "test")
and if not, by what mechanism can m make use of the names x_1 ... x_n? Can m actually have a type like List Name → TC ⊤, contrary to the documentation?
Based on the way Ulf uses unquoteDecl, I have the impression that you need to list on the LHS the names which are going to extend the scope.
The problem with your setup is that you don't know the Name as you generate a fresh one from a String and have no way of getting hold of it AFAIK. I have the impression that freshName is only supposed to be used to generate internal names from inside a tactic.
If you make testDefineName' take a Name rather than a String then everything works out:
testDefineName' : Name → TC Type → TC Term → TC ⊤
testDefineName' n t a = bindTC t
$ λ t' → bindTC a
$ λ a' → bindTC (declareDef (arg (arg-info visible relevant) n) t')
$ λ _ → defineFun n ((clause [] a') ∷ [])
unquoteDecl test = testDefineName' test (quoteTC ℕ) (quoteTC zero)

How to prove that equal function types have equal domains?

I want to prove
∀ {ℓ} {A B C D : Set ℓ} → (A → B) ≡ (C → D) → A ≡ C
(and similar for the codomain).
If I had a function domain that returns the domain of a function type, I could write the proof as
cong domain
but I don't think it's possible to write such a function.
Is there any way to do this?
I posed a very similar question on the Agda mailing list a few months ago, see: http://permalink.gmane.org/gmane.comp.lang.agda/5624. The short answer is that you cannot prove this in Agda.
The technical reason is that the unification algorithm used internally by Agda for pattern matching doesn't include a case for problems of the form (A → B) ≡ (C → D), so this definition does not typecheck:
cong-domain : ∀ {ℓ} {A B C D : Set ℓ} → (A → B) ≡ (C → D) → A ≡ C
cong-domain refl = refl
It is also impossible to define the function domain directly. Think about it: what should be the domain of a type that is not a function type, e.g. Bool?
The deeper reason why you cannot prove this is that it would be incompatible with the univalence axiom from Homotopy Type Theory. In an answer given by Guillaume Brunerie on my mail, he gives the following example: Consider the two types Bool -> Bool and Unit -> (Bool + Bool). Both have 4 elements, so we can use the univalence axiom to give a proof of type Bool -> Bool ≡ Unit -> (Bool + Bool) (in fact there are 24 different proofs). But clearly we do not want Bool ≡ Unit! So in the presence of univalence, we cannot assume that equal function types have equal domains.
In the end, I 'solved' this problem by passing an extra argument of type A ≡ C everywhere it was needed. I know it's not ideal, but maybe you can do the same.
I should also note that Agda does include an option for injective type constructors, which you can enable by putting {-# OPTIONS --injective-type-constructors #-} at the top of your .agda file. This allows you for example to prove A ≡ B from List A ≡ List B, but unfortunately this only works for type constructors such as List, and not for function types.
You could of course always make a feature request at https://code.google.com/p/agda/issues/list to add a option --injective-function-types to Agda. This option would be incompatible with univalence, but so is --injective-type-constructors, yet for many applications this is not a real problem. I feel that the main Agda developers are usually very open to such requests, and very fast to add them to the development version of Agda.

How dangerous is trustMe?

Here's what I understand about Relation.Binary.PropositionalEquality.TrustMe.trustMe: it seems to take an arbitrary x and y, and:
if x and y are genuinely equal, it becomes refl
if they are not, it behaves like postulate lie : x ≡ y.
Now, in the latter case it can easily make Agda inconsistent, but this in itself is not so much a problem: it just means that any proof using trustMe is a proof by appeal to authority. Moreover, though you can use such things to write coerce : {A B : Set} -> A -> B, it turns out to be the case that coerce {ℕ} {Bool} 0 doesn't reduce (at least, not according to C-c C-n), so it's really not analogous to, say, Haskell's semantic-stomping unsafeCoerce.
So what do I have to fear from trustMe? On the other hand, is there ever a reason to use it outside of implementing primitives?
Indeed, attempting to pattern match on trustMe which does not evaluate to refl results in a stuck term. Perhaps it is enlightening to see (part of) the code that defines the primitive operation behind trustMe, primTrustMe:
(u', v') <- normalise (u, v)
if (u' == v') then redReturn (refl $ unArg u) else
return (NoReduction $ map notReduced [a, t, u, v])
Here, u and v represent the terms x and y, respectively. The rest of the code can be found in the module Agda.TypeChecking.Primitive.
So yes, if x and y are not definitionally equal, then primTrustMe (and by extension trustMe) behaves as a postulate in the sense that evaluation simply gets stuck. However, there's one crucial difference when compiling Agda down to Haskell. Taking a look at the module Agda.Compiler.MAlonzo.Primitives, we find this code:
("primTrustMe" , Right <$> do
refl <- primRefl
flip runReaderT 0 $
term $ lam "a" (lam "A" (lam "x" (lam "y" refl))))
This looks suspicious: it always returns refl no matter what x and y are. Let's have a test module:
module DontTrustMe where
open import Data.Nat
open import Data.String
open import Function
open import IO
open import Relation.Binary.PropositionalEquality
open import Relation.Binary.PropositionalEquality.TrustMe
postulate
trustMe′ : ∀ {a} {A : Set a} {x y : A} → x ≡ y
transport : ℕ → String
transport = subst id (trustMe {x = ℕ} {y = String})
main = run ∘ putStrLn $ transport 42
Using trustMe inside transport, compiling the module (C-c C-x C-c) and running the resulting executable, we get... you guessed it right - a segfault.
If we instead use the postulate, we end up with:
DontTrustMe.exe: MAlonzo Runtime Error:
postulate evaluated: DontTrustMe.trustMe′
If you do not intend to compile your programs (at least using MAlonzo) then inconsistency should be your only worry (on the other hand, if you only typecheck your programs then inconsistency usually is kind of a big deal).
There are two use cases I can think of at the moment, first is (as you've said) for implementing primitives. The standard library uses trustMe in three places: in implementation of decidable equality for Names (Reflection module), Strings (Data.String module) and Chars (Data.Char module).
The second one is much like the first one, except that you provide the data type and the equality function yourself and then use trustMe to skip the proving and just use the equality function to define a decidable equality. Something like:
open import Data.Bool
open import Relation.Binary
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
data X : Set where
a b : X
eq : X → X → Bool
eq a a = true
eq b b = true
eq _ _ = false
dec-eq : Decidable {A = X} _≡_
dec-eq x y with eq x y
... | true = yes trustMe
... | false = no whatever
where postulate whatever : _
However, if you screw up eq, the compiler cannot save you.

Resources