I can trivially prove that not equals is irrelevant with function extensionality:
open import Relation.Binary.PropositionalEquality using (_≢_)
open import Relation.Binary using (Irrelevant)
open import Relation.Nullary.Negation using (contradiction)
open import Axiom.Extensionality.Propositional using (Extensionality)
postulate
fun-ext : ∀ {ℓ₁ ℓ₂} → Extensionality ℓ₁ ℓ₂
≢-irrelevant : ∀ {a} {A : Set a} → Irrelevant {A = A} _≢_
≢-irrelevant {x} {y} [x≉y]₁ [x≉y]₂ = fun-ext (λ x≈y → contradiction x≈y [x≉y]₁)
This seems impossible to prove without funext when A is polymorphic but is it possible when A = ℕ or A = Bool?
This is not provable without funext. We did consider changing the definition of the empty type to make these provable however it was deemed too invasive a change.
Related
I am trying to prove decidable equality of a data type in Agda using the Agda stdlib. I have the following code, but I am unsure what to fill in the hole. The goal seems to make sense, but actually constructing it is challenging.
Is this possible in Agda and are there any ideas on how to solve this?
open import Data.String as String hiding (_≟_)
open import Relation.Nullary
open import Relation.Binary
open import Relation.Binary.PropositionalEquality
module Problem1 where
data Test : Set where
test : String → Test
infix 4 _≟_
_≟_ : Decidable {A = Test} _≡_
test x ≟ test x₁ with x String.≟ x₁
... | yes refl = yes refl
... | no ¬a = no {!!}
The hole:
Goal: ¬ test x ≡ test x₁
————————————————————————————————————————————————————————————
¬a : ¬ x ≡ x₁
x₁ : ℕ
x : ℕ
This is actually a one liner, relying on case splitting over the equality proof inside an anonymous function, as follows:
... | no ¬a = no λ {refl → ¬a refl}
I am not confident enough to try proving properties about the AVL tree that is there, so I want to try something simpler. I could implement it on my own, but do not want to spend time doing that if it is already hiding in the library somewhere.
You could use a list of pairs and the notion of membership can then be encoded via Any.
Bits of a very basic library:
open import Data.List.Base using (List)
open import Data.List.Relation.Unary.Any
open import Data.Maybe
open import Data.Product
open import Function
open import Relation.Binary
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
AssocList : Set → Set → Set
AssocList A B = List (A × B)
private
variable
A B : Set
_∈_ : A → AssocList A B → Set
a ∈ abs = Any ((a ≡_) ∘ proj₁) abs
module Decidable {A : Set} (_≟_ : Decidable {A = A} _≡_) where
_∈?_ : Decidable (_∈_ {A} {B})
a ∈? abs = any ((a ≟_) ∘ proj₁) abs
_‼_ : (abs : AssocList A B) (a : A) → Maybe B
abs ‼ a with a ∈? abs
... | yes p = just (proj₂ (lookup p))
... | no ¬p = nothing
I'm proving stuff in Agda, and some of my files are starting to get a bit long and cluttered (even after I refactored into smaller modules). Is it possible to have two files, one of which contains type signatures of theorems only, and another which contains those theorems and proofs? I looked at the abstract keyword, but that doesn't quite seem to do the right thing.
Of course, I can put all the type signatures at the top of the file, and have all the proofs at the bottom of the file; but it seems cleaner if I could have the statements in a file to themselves.
You could give names to the types of your lemmas. E.g. in file Statement.agda:
module Statement where
open import Agda.Builtin.Nat
open import Agda.Builtin.Equality
+-sym : Set
+-sym = ∀ m n → m + n ≡ n + m
And in file Proof.agda:
module Proof where
open import Agda.Builtin.Nat
open import Agda.Builtin.Equality
import Statement
+-sym : Statement.+-sym
+-sym m n = {!!}
In case your definition is level-polymorphic, Agda unfortunately doesn't have a (surface) name for types of the form ∀ {ℓ : Level} → .... You will have to take the levels as arguments in Statement and quantify over them universally when using the statement in Proof. This would give you something like this:
In Statement.agda:
open import Agda.Primitive
data ⊥ : Set where
⊥-elim : (ℓ : Level) → Set (lsuc ℓ)
⊥-elim ℓ = ∀ {A : Set ℓ} → ⊥ → A
In Proof.agda:
⊥-elim : ∀ {ℓ} → Statement.⊥-elim ℓ
⊥-elim = {!!}
Reading this answer prompted me to try to construct, and then prove, the canonical form of polymorphic container functions. The construction was straightforward, but the proof stumps me. Below is a simplified-minimized version of how I tried to write the proof.
The simplified version is proving that sufficiently polymorphic functions, due to parametricity, can't change their behaviour only based on the choice of parameter. Let's say we have functions of two arguments, one of a fixed type and one parametric:
PolyFun : Set → Set _
PolyFun A = ∀ {X : Set} → A → X → A
the property I'd like to prove:
open import Relation.Binary.PropositionalEquality
parametricity : ∀ {A X Y} → (f : PolyFun A) → ∀ a x y → f {X} a x ≡ f {Y} a y
parametricity f a x y = {!!}
Are statements like that provable from inside Agda?
Nope, there's no parametricity principle accessible in Agda (yet! [1]).
However you can use these combinators to build the type of the corresponding free theorem and postulate it:
http://wiki.portal.chalmers.se/agda/pmwiki.php?n=Libraries.LightweightFreeTheorems
[1] http://www.cse.chalmers.se/~mouling/share/PresheafModelParametericTT.pdf
The Agda standard library provides a data type Maybe accompanied with a view Any.
Then there is the property Is-just defined using Any. I found working with this type difficult as the standard library provides exactly no tooling for Any.
Thus I am looking for examples on how to work with Is-just effectively. Is there an open source project that uses it?
Alternatively, I am seeking how to put it to good use:
Given Is-just m and Is-nothing m, how to eliminate? Can Relation.Nullary.Negation.contradiction be used here?
Given a property p : ... → (mp : Is-just m) → ... → ... ≡ to-witness mp that needs to be shown inductively by p ... = {! p ... (subst Is-just m≡somethingelse mp) ... !}, the given term does not fill the hole, because it has type ... ≡ to-witness (subst Is-just m≡somethingelse mp).
Often it seems easier to work with Σ A (_≡_ m ∘ just) than Is-just m.
Regarding your first question, it is possible to derive a contradiction from having both Is-just m and Is-nothing m in context. You can then use ⊥-elim to prove anything.
module isJust where
open import Level
open import Data.Empty
open import Data.Maybe
contradiction :
{ℓ : Level} {A : Set ℓ} {m : Maybe A}
(j : Is-just m) (n : Is-nothing m) → ⊥
contradiction (just _) (just pr) = pr
The second one is a bit too abstract for me to be sure whether what I'm suggesting will work but the usual strategies are to try to pattern match on the value of type Maybe A or on the proof that Is-just m.
As for using another definition of Is-just, I tend to like
open import Data.Bool
isJust : {ℓ : Level} {A : Set ℓ} (m : Maybe A) → Set
isJust m = T (is-just m)
because it computes.