Coq: import information about instances - typeclass

Section Definitions.
Definition eq_dec X := forall x y : X, {x=y} + {x <> y}.
Existing Class eq_dec.
(* Any function that uses eq_dec. Doesn't matter -- ↓ ↓ ↓ *)
Definition f {X: Type} {DecX: eq_dec X} (x y: X) := x = y.
End Definitions.
Section MySection.
Context {T: Type}.
Hypothesis TEqDec: eq_dec T.
Inductive myType :=
| C: T -> myType.
Instance myTypeEqDec : eq_dec myType.
Proof. ... Defined.
(* Everything is ok *)
Example example1: forall (t1 t2: myType), f t1 t2.
Proof. ... Qed.
End MySection.
Section AnotherSection.
Context {T: Type}.
Hypothesis TEqDec: eq_dec T.
(* Now I must explicitly specify this -- ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
Example example2: forall (t1 t2: #myType T), #f _ (#myTypeEqDec _ TEqDec) t1 t2.
Proof. ... Qed.
End AnotherSection.
As you can see in example1 Coq is able to find instance-information about myType. But after I change the section, all the information about the instances disappears and I have to specify it explicitly. So, when I have many type-classes and instances, code rapidly becomes messy. Obviously, I should somehow get that information back into the context. What is the proper way to do so?

Just add the Global modifier to your instance declaration, like this:
Global Instance myTypeEqDec : eq_dec myType.
(* ... *)
As stated in the reference manual,
One can use the Global modifier on instances declared in a section so that their generalization is automatically redeclared after the section is closed.

Related

Could these be used as Racket definitions for cons, first, and rest?

I am trying to follow along this Racket tutorial:
https://cs.uwaterloo.ca/~plragde/flaneries/TYR/Pure_Functional_Programming.html
and it describes these alternatives to the actual implementations. I know what cons, first and rest do, and I understand how lambda functions work, but I cannot figure out how these successfully implement cons, first and rest.
(define (cons f r) (lambda (b) (if b f r)))
(define (first lst) (lst true))
(define (rest lst) (lst false))
Maybe I have misinterpretted what they are supposed to be. Here is what the tutorial says:
As another example of the use of closures, consider the following "alternative" implementation of the basic list primitives.
Could someone clarify?
#lang racket
(define (cons f r) (lambda (b) (if b f r)))
Here cons has been redefined to be a procedure which takes two arguments f and r, and returns a procedure which takes one argument b. Let's try it:
cons-func.rkt> (define a-cons (cons 1 2))
Now we have called the cons procedure with the values 1 and 2; cons has returned a procedure which we have named a-cons.
cons-func.rkt> a-cons
#<procedure:...ratch/cons-func.rkt:3:19>
Now, a-cons is a procedure that takes a single argument; if that argument is true, then the first of two values passed in the earlier call to cons is returned; if instead the argument to a-cons is false, then the second of the two earlier arguments is returned:
cons-func.rkt> (a-cons true)
1
cons-func.rkt> (a-cons false)
2
There are two values stored in the closure returned by our new cons, and both of them can be retrieved. This is effectively a cons cell. Let's add some sugar to make this nicer to use. Here first and rest just do what we did by hand a moment ago:
(define (first lst) (lst true))
(define (rest lst) (lst false))
Now we can access the two parts of our cons cell in the usual way:
cons-func.rkt> (first a-cons)
1
cons-func.rkt> (rest a-cons)
2
This new implementation of cons cells is not compatible with the old one. For example, we have not redefined car and cdr, and the normal implementation of those procedures will not work with our new cons cells:
cons-func.rkt> (car a-cons)
; car: contract violation
; expected: pair?
; given: #<procedure:...ratch/cons-func.rkt:3:19>
We can use our new cons cells to define list:
(define (list . xs)
(if (null? xs)
'()
(cons (car xs)
(apply list (cdr xs)))))
Here we are cheating a bit, using the dot syntax to capture an arbitrary number of arguments in a list (the regular kind). We use car and cdr to take this list apart (because they work with regular lists), and reassemble it with the new cons into a closure-based list.
cons-func.rkt> (define a-list (list 'a 'b 'c))
cons-func.rkt> a-list
#<procedure:...ratch/cons-func.rkt:3:19>
Here you can see that the list created by our new list procedure, named a-list, is itself a procedure. We can call our first and rest procedures on a-list:
cons-func.rkt> (first a-list)
'a
cons-func.rkt> (rest a-list)
#<procedure:...ratch/cons-func.rkt:3:19>
cons-func.rkt> (first (rest a-list))
'b
cons-func.rkt> (first (rest (rest a-list)))
'c
cons-func.rkt> (rest (rest (rest a-list)))
'()
So, it seems that our closure-based cons cells behave as regular cons cells, though the underlying implementation is not compatible with Rackets own cons and list accessor procedures, and we can use these closure-based cons cells to create closure-based lists. If someone had the time and inclination, they could probably implement a whole Scheme around these closure-based cons cells.
Defining a data structure is a process of 2 steps.
defining the axioms of the data structure, i.e. the abstract data structure
defining the implementation which must obey the axioms.
Whatever implementation you create is correct as time as the axioms are true in that implementation.
The axioms for the lisp constructor differ from implementation to implementation. In scheme they are so
(CAR (CONS x y)) = x
(CDR (CONS x y)) = y
Each implementation that creates the functions CONS, CAR, CDR that obey this is correct and can be used as implementation for cons cells contructor.
The things are not so direct however, as the axioms of CONS can interact with other axioms of the system. For example, some systems impose the axiom:
(EQ (CONS x y) (CONS X Y))
and in this case you need to take care in the implementation such that cons to check if there is already a (X . Y) pair allocated, and not duplicate the memory.
The other answers detail the implementation of cons with functions.
Explanation through the substitution method:
The results you want are
(first (cons a b))
—> a
and
(rest (cons a b))
—> b
These are all the requirements for the three primitives.
Now consider (cons x y): replace f and r in the definition of cons with x and y – that is,
(cons x y)
—> (lambda (b) (if b x y))
Now, (first (cons x y)) is
(first (lambda (b) (if b x y)))
—> ((lambda (b) (if b x y)) true)
—> (if true x y)
—> x
and (rest (cons x y)) is
(first (lambda (b) (if b x y)))
—> ((lambda (b) (if b x y)) false)
—> (if false x y)
—> y

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.

Using multiple EqReasoning instantiations conveniently

Is there a way to conveniently use multiple instantiations of EqReasoning where the underlying Setoid is not necessarily semantic equality (i.e. ≡-Reasoning cannot be used)? The reason that ≡-Reasoning is convenient is that the type argument is implicit and it uniquely determines the Setoid in use by automatically selecting semantic equality. When using arbitrary Setoids there is no such unique selection. However a number of structures provide a canonical way to lift a Setoid:
Data.Maybe and Data.Covec have a setoid member.
Data.Vec.Equality.Equality provides enough definitions to write a canonical Setoid lifting for Vec as well. Interestingly there is also is a slightly different equality available at Relation.Binary.Vec.Pointwise, but it does not provide a direct lifting either albeit implementing all the necessary bits.
Data.List ships a Setoid lifting in Relation.Binary.List.Pointwise.
Data.Container also knows how to lift a Setoid.
By using any of these structures, one automatically gets to work with multiple Setoids even if one started out with one. When proofs use these structures (multiple of them in a single proof), it becomes difficult to write down the proof, because EqReasoning must be instantiated for all of them even though each particular Setoid is kind of obvious. This can be done by renaming begin_, _≈⟨_⟩_ and _∎, but I don't consider this renaming convenient.
Consider for example, a proof in the Setoid of Maybe where a sequence of arguments needs to be wrapped in Data.Maybe.Eq.just (think cong just) or a proof in an arbitrary Setoid that temporarily needs to wrap things in a just constructor exploiting its injectivity.
Normally, the only way Agda can pick something for you is when it is uniquely determined by the context. In the case of EqReasoning, there isn't usually enough information to pin down the Setoid, even worse actually: you could have two different Setoids over the same Carrier and _≈_ (consider for example two definitionally unequal proofs of transitivity in the isEquivalence field).
However, Agda does allow special form of implicit arguments, which can be filled as long as there is only one value of the desired type. These are known as instance arguments (think instance as in Haskell type class instances).
To demonstrate roughly how this works:
postulate
A : Set
a : A
Now, instance arguments are wrapped in double curly braces {{}}:
elem : {{x : A}} → A
elem {{x}} = x
If we decide to later use elem somewhere, Agda will check for any values of type A in scope and if there's only one of them, it'll fill that one in for {{x : A}}. If we added:
postulate
b : A
Agda will now complain that:
Resolve instance argument _x_7 : A. Candidates: [a : A, b : A]
Because Agda already allows you to perform computations on type level, instance arguments are deliberately limited in what they can do, namely Agda won't perform recursive search to fill them in. Consider for example:
eq : ... → IsEquivalence _≈_ → IsEquivalence (Eq _≈_)
where Eq is Data.Maybe.Eq mentioned in your question. When you then require Agda to fill in an instance argument of a type IsEquivalence (Eq _≈_), it won't try to find something of type IsEquivalence _≈_ and apply eq to it.
With that out of the way, let's take a look at what could work. However, bear in mind that all this stands on unification and as such you might need to push it in the right direction here and there (and if the types you are dealing with become complex, unification might require you to give it so many directions that it won't be worth it in the end).
Personally, I find instance arguments a bit fragile and I usually avoid them (and from a quick check, it would seem that so does the standard library), but your experience might vary.
Anyways, here we go. I constructed a (totally nonsensical) example to demonstrate how to do it. Some boilerplate first:
open import Data.Maybe
open import Data.Nat
open import Relation.Binary
import Relation.Binary.EqReasoning as EqR
To make this example self-contained, I wrote some kind of Setoid with natural numbers as its carrier:
data _≡ℕ_ : ℕ → ℕ → Set where
z≡z : 0 ≡ℕ 0
s≡s : ∀ {m n} → m ≡ℕ n → suc m ≡ℕ suc n
ℕ-setoid : Setoid _ _
ℕ-setoid = record
{ _≈_ = _≡ℕ_
; isEquivalence = record
{ refl = refl
; sym = sym
; trans = trans
}
}
where
refl : Reflexive _≡ℕ_
refl {zero} = z≡z
refl {suc _} = s≡s refl
sym : Symmetric _≡ℕ_
sym z≡z = z≡z
sym (s≡s p) = s≡s (sym p)
trans : Transitive _≡ℕ_
trans z≡z q = q
trans (s≡s p) (s≡s q) = s≡s (trans p q)
Now, the EqReasoning module is parametrized over a Setoid, so usually you do something like this:
open EqR ℕ-setoid
However, we'd like to have the Setoid parameter to be implicit (instance) rather than explicit, so we define and open a dummy module:
open module Dummy {c ℓ} {{s : Setoid c ℓ}} = EqR s
And we can write this simple proof:
idʳ : ∀ n → n ≡ℕ (n + 0)
idʳ 0 = z≡z
idʳ (suc n) = begin
suc n ≈⟨ s≡s (idʳ n) ⟩
suc (n + 0) ∎
Notice that we never had to specify ℕ-setoid, the instance argument picked it up because it was the only type-correct value.
Now, let's spice it up a bit. We'll add Data.Maybe.setoid into the mix. Again, because instance arguments do not perform a recursive search, we'll have to define the setoid ourselves:
Maybeℕ-setoid = setoid ℕ-setoid
_≡M_ = Setoid._≈_ Maybeℕ-setoid
I'm going to postulate few stupid things just to demonstrate that Agda indeed picks correct setoids:
postulate
comm : ∀ m n → (m + n) ≡ℕ (n + m)
eq0 : ∀ n → n ≡ℕ 0
eq∅ : just 0 ≡M nothing
lem : ∀ n → just (n + 0) ≡M nothing
lem n = begin
just (n + 0) ≈⟨ just
(begin
n + 0 ≈⟨ comm n 0 ⟩
n ≈⟨ eq0 n ⟩
0 ∎
)⟩
just 0 ≈⟨ eq∅ ⟩
nothing ∎
I figured an alternative to the proposed solution using instance arguments that slightly bends the requirements, but fits my purpose. The major burden in the question was having to explicitly open EqReasoning multiple times and especially having to invent new names for the contained symbols. A slight improvement would be to pass the correct Setoid once per relation proof. In other words passing it to begin_ or _∎ somehow. Then we could make the Setoid implicit for all the other functions!
import Relation.Binary.EqReasoning as EqR
import Relation.Binary using (Setoid)
module ExplicitEqR where
infix 1 begin⟨_⟩_
infixr 2 _≈⟨_⟩_ _≡⟨_⟩_
infix 2 _∎
begin⟨_⟩_ : ∀ {c l} (X : Setoid c l) → {x y : Setoid.Carrier X} → EqR._IsRelatedTo_ X x y → Setoid._≈_ X x y
begin⟨_⟩_ X p = EqR.begin_ X p
_∎ : ∀ {c l} {X : Setoid c l} → (x : Setoid.Carrier X) → EqR._IsRelatedTo_ X x x
_∎ {X = X} = EqR._∎ X
_≈⟨_⟩_ : ∀ {c l} {X : Setoid c l} → (x : Setoid.Carrier X) → {y z : Setoid.Carrier X} → Setoid._≈_ X x y → EqR._IsRelatedTo_ X y z → EqR._IsRelatedTo_ X x z
_≈⟨_⟩_ {X = X} = EqR._≈⟨_⟩_ X
_≡⟨_⟩_ : ∀ {c l} {X : Setoid c l} → (x : Setoid.Carrier X) → {y z : Setoid.Carrier X} → x ≡ y → EqR._IsRelatedTo_ X y z → EqR._IsRelatedTo_ X x z
_≡⟨_⟩_ {X = X} = EqR._≡⟨_⟩_ X
Reusing the nice example from Vitus answer, we can write it:
lem : ∀ n → just (n + 0) ≡M nothing
lem n = begin⟨ Data.Maybe.setoid ℕ-setoid ⟩
just (n + 0) ≈⟨ just
(begin⟨ ℕ-setoid ⟩
n + 0 ≈⟨ comm n 0 ⟩
n ≈⟨ eq0 n ⟩
0 ∎
)⟩
just 0 ≈⟨ eq∅ ⟩
nothing ∎
where open ExplicitEqR
One still has to mention the Setoids in use, to avoid the use of instance arguments as presented by Vitus. However the technique makes it significantly more convenient.

Types containing with/rewrite clauses in agda, or, how to use rewrite instead of subst?

First some boring imports:
import Relation.Binary.PropositionalEquality as PE
import Relation.Binary.HeterogeneousEquality as HE
import Algebra
import Data.Nat
import Data.Nat.Properties
open PE
open HE using (_≅_)
open CommutativeSemiring commutativeSemiring using (+-commutativeMonoid)
open CommutativeMonoid +-commutativeMonoid using () renaming (comm to +-comm)
Now suppose that I have a type indexed by, say, the naturals.
postulate Foo : ℕ -> Set
And that I want to prove some equalities about functions operating on this type Foo. Because agda is not very smart, these will be heterogeneous equalities. A simple example would be
foo : (m n : ℕ) -> Foo (m + n) -> Foo (n + m)
foo m n x rewrite +-comm n m = x
bar : (m n : ℕ) (x : Foo (m + n)) -> foo m n x ≅ x
bar m n x = {! ?0 !}
The goal in bar is
Goal: (foo m n x | n + m | .Data.Nat.Properties.+-comm n m) ≅ x
————————————————————————————————————————————————————————————
x : Foo (m + n)
n : ℕ
m : ℕ
What are these |s doing in the goal? And how do I even begin to construct a term of this type?
In this case, I can work around the problem by manually doing the substitution with subst, but that gets really ugly and tedious for larger types and equations.
foo' : (m n : ℕ) -> Foo (m + n) -> Foo (n + m)
foo' m n x = PE.subst Foo (+-comm m n) x
bar' : (m n : ℕ) (x : Foo (m + n)) -> foo' m n x ≅ x
bar' m n x = HE.≡-subst-removable Foo (+-comm m n) x
Those pipes indicate that reduction is suspended pending the result of the expressions in question, and it typically boils down to the fact that you had a with block whose result you need to know to proceed. This is because the rewrite construct just expands to a with of the expression in question along with any auxiliary values that might be needed to make it work, followed by a match on refl.
In this case, it just means that you need to introduce the +-comm n m in a with block and pattern match on refl (and you'll probably need to bring n + m into scope too, as it suggests, so the equality has something to talk about). The Agda evaluation model is fairly straightforward, and if you pattern match on something (except for the faux pattern matches on records), it won't reduce until you pattern match on that same thing. You might even be able to get away with rewriting by the same expression in your proof, since it just does what I outlined for you.
More precisely, if you define:
f : ...
f with a | b | c
... | someDataConstructor | boundButNonConstructorVariable | someRecordConstructor = ...
and then you refer to f as an expression, you will get the pipes you observed for expression a only, because it matches on someDataConstructor, so at the very least to get f to reduce you will need to introduce a and then match on someDataConstructor from it. On the other hand, b and c, although they were introduced in the same with block, do no halt evaluation, because b doesn't pattern match, and c's someRecordConstructor is known statically to be the only possible constructor because it's a record type with eta.

How to determine the FIRST set of E in this grammar?

I wonder how to determine the FIRST set of E with grammar:
E -> XYE | e
X -> x
Y -> y
Can anyone give me some direction?
Well, assuming that you're starting with E, then either the first terminal is x via the E→XYE production (since X always produces x) or it is e via the E→e production. So First(E) = {x,e}.
That seems pretty straightforward...
Treat rules of the form A -> ...x... | ...y ....
as two rules A -> ...x... and B -> ...y...
Form a set S initially containing rules of form E-> ....
then
Set a set P to empty.
Set a set F to empty.
Repeat until S is empty
Choose element of S, and call it R
If R is in P, remove R from S
Elsif R is of the form A -> b ...
then { add b to F,
add R to P,
remove R from S}
Else (R is the form A -> B ...)
then { place all rules of form B -> ... into S
remove R from S}
End
WHen the loop terminates, F contains the tokens which
are the First(F).
This does not take into account empty productions.

Resources