Is there an associative list in the standard library? - agda

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

Related

Decidable equality of data types in Agda

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}

Is it possible to prove not equals is irrelevant without funext?

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.

How to deal with conflicting module definitions?

open import Data.Vec
open import Data.Nat
open import Data.Fin
open import Data.Integer
open import Data.Rational
open import Data.Product
open import Relation.Binary.PropositionalEquality using (_≡_; refl)
Infoset = ℕ
Size = ℕ
Player = ℤ
data GameTree (infoset-size : Infoset → Size) : Set where
Terminal : (reward : ℚ) → GameTree infoset-size
Response : (id : Infoset) → (subnodes : Vec (GameTree infoset-size) (infoset-size id)) → GameTree infoset-size
record Policy (infoset-size : Infoset → Size) : Set where
field
σ : ∀ (id : Infoset) → Vec ℚ (infoset-size id)
wf-elem : ∀ (id : Infoset) (i : Fin (infoset-size id)) → 0ℚ Data.Rational.≤ lookup (σ id) i × lookup (σ id) i Data.Rational.≤ 1ℚ
Had I written the above like 0ℚ ≤ lookup (σ id) i × lookup (σ id) i ≤ 1ℚ I would have gotten the following type error.
Ambiguous name _≤_. It could refer to any one of
Data.Nat._≤_ bound at
C:\Users\Marko\AppData\Roaming\cabal\x86_64-windows-ghc-8.6.5\Agda-2.6.0\lib\agda-stdlib\src\Data\Nat\Base.agda:33,6-9
Data.Fin._≤_ bound at
C:\Users\Marko\AppData\Roaming\cabal\x86_64-windows-ghc-8.6.5\Agda-2.6.0\lib\agda-stdlib\src\Data\Fin\Base.agda:218,1-4
Data.Integer._≤_ bound at
C:\Users\Marko\AppData\Roaming\cabal\x86_64-windows-ghc-8.6.5\Agda-2.6.0\lib\agda-stdlib\src\Data\Integer\Base.agda:44,6-9
Data.Rational._≤_ bound at
C:\Users\Marko\AppData\Roaming\cabal\x86_64-windows-ghc-8.6.5\Agda-2.6.0\lib\agda-stdlib\src\Data\Rational\Base.agda:71,6-9
Is there some elegant way to induce to make Agda infer the right functions to use on its own? Here it should be capable of doing the right thing given that the types are known.
Agda allows ambiguous constructors and ambiguous projections, but any other names have to be unambigous at the position where they are used.
To avoid ambiguity, you can rename a symbol using the open import Data.Nat renaming (_≤_ to _≤Nat_) syntax. Alternatively, you can use open import Data.Nat as Nat and use x Nat.≤ y.
A different library design could make use of instance arguments to provide ad-hoc overloading (for example the Agda prelude).

Agda: separate declaration from definition

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 = {!!}

Is there any non-trivial code that uses Data.Maybe.Is-just?

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.

Resources