Does Agda treat records and datatypes differently for the purposes of termination-checking? - records

Here is an example of some Agda (2.4.2) code defining games and a binary operation on games.
module MWE where
open import Data.Sum
open import Size
data Game (i : Size) : Set₁ where
game : {Move : Set} → {<i : Size< i} → (play : Move → Game <i) → Game i
_∧_ : ∀ {i j} → Game i → Game j → Game ∞
_∧_ {i} {j} (game {Move/g} {<i} play/g) (game {Move/h} {<j} play/h)
= game {∞} {Move/g ⊎ Move/h}
λ { (inj₁ x) → _∧_ {<i} {j} (play/g x) (game play/h)
; (inj₂ y) → _∧_ {i} {<j} (game play/g) (play/h y) }
This code type- and termination-checks. However, if I replace the definition of Game with a record definition, like so:
record Game (i : Size) : Set₁ where
inductive
constructor game
field
{Move} : Set
{<i} : Size< i
play : Move → Game <i
Agda no longer believes the definition of _∧_ to be terminating, even though the value of either i or j decreases in each recursive call. As far as I am aware, these two definitions of Game should be equivalent; what causes Agda to successfully termination-check the former, but not the latter?

Related

How do you use the Ring solver in Cubical Agda?

I have started playing around with Cubical Agda. Last thing I tried doing was building the type of integers (assuming the type of naturals is already defined) in a way similar to how it is done in classical mathematics (see the construction of integers on wikipedia). This is
data dInt : Set where
_⊝_ : ℕ → ℕ → dInt
canc : ∀ a b c d → a + d ≡ b + c → a ⊝ b ≡ c ⊝ d
trunc : isSet (dInt)
After doing that, I wanted to define addition
_++_ : dInt → dInt → dInt
(x ⊝ z) ++ (u ⊝ v) = (x + u) ⊝ (z + v)
(x ⊝ z) ++ canc a b c d u i = canc (x + a) (z + b) (x + c) (z + d) {! !} i
...
I am now stuck on the part between the two braces. A term of type x + a + (z + d) ≡ z + b + (x + c) is asked. Not wanting to prove this by hand, I wanted to use the ring solver made in Cubical Agda. But I could never manage to make it work, even trying to set it up for simple ring equalities like x + x + x ≡ 3 * x.
How can I make it work ? Is there a minimal example to make it work for naturals ? There is a file NatExamples.agda in the library, but it makes you have to rewrite your equalities in a convoluted way.
You can see how the solver for natural numbers is supposed to be used in this file in the cubical library:
Cubical/Tactics/NatSolver/Examples.agda
Note that this solver is different from the solver for commutative rings, which is designed for proving equations in abstract rings and is explained here:
Cubical/Tactics/CommRingSolver/Examples.agda
However, if I read your problem correctly, the equality you want to prove requires the use of other propositional equalities in Nat. This is not supported by any solver in the cubical library (as far as I know, also the standard library doesn't support it). But of course, you can use the solver for all the steps that don't use other equalities.
Just in case you didn't spot this: here is a definition of the integers in math-style using the SetQuotients of the cubical library. SetQuotients help you to avoid the work related to your third constructor trunc. This means you basically just need to show some constructions are well defined as you would in 'normal' math.
I've successfully used the ring solver for exactly the same problem: defining Int as a quotient of ℕ ⨯ ℕ. You can find the complete file here, the relevant parts are the following:
Non-cubical propositional equality to path equality:
open import Cubical.Core.Prelude renaming (_+_ to _+̂_)
open import Relation.Binary.PropositionalEquality renaming (refl to prefl; _≡_ to _=̂_) using ()
fromPropEq : ∀ {ℓ A} {x y : A} → _=̂_ {ℓ} {A} x y → x ≡ y
fromPropEq prefl = refl
An example of using the ring solver:
open import Function using (_$_)
import Data.Nat.Solver
open Data.Nat.Solver.+-*-Solver
using (prove; solve; _:=_; con; var; _:+_; _:*_; :-_; _:-_)
reorder : ∀ x y a b → (x +̂ a) +̂ (y +̂ b) ≡ (x +̂ y) +̂ (a +̂ b)
reorder x y a b = fromPropEq $ solve 4 (λ x y a b → (x :+ a) :+ (y :+ b) := (x :+ y) :+ (a :+ b)) prefl x y a b
So here, even though the ring solver gives us a proof of _=̂_, we can use _=̂_'s K and _≡_'s reflexivity to turn that into a path equality which can be used further downstream to e.g. prove that Int addition is representative-invariant.

Translating Coq Definitions to agda?

I'm wondering if there is a systematic way to interpret Coq Definitions as agda programs. I'm working through translating part of programming foundations and am not able to get the tUpdate function to work below. Why is this failing. The coq code is commented.
--Definition total_map (A : Type) := string -> A.
totalMap : Set → Set
totalMap A = String → A
-- Definition t_empty {A : Type} (v : A) : total_map A :=
-- (fun _ => v).
tEmpty : {A : Set} (v : A) → totalMap A
tEmpty = λ v x → v
-- Definition t_update {A : Type} (m : total_map A)
-- (x : string) (v : A) :=
-- fun x' => if eqb_string x x' then v else m x'.
tUpdate : {A : Set} (m : totalMap A) (x : String) (v : A) → Set
tUpdate m x v = λ x' → (if (x == x') then v else m x')
The lambda term produces the below error
(x' : String) → A !=< Set of type Set
when checking that the expression
λ x' → if x == x' then v else m x' has type Set
Is this a correct general schema for doing this translation, e.g., is this translation sound and complete?
Edit:
I realized update was supposed to return a map, but i'm confused as it coq can seemingly infer this while agda can't? I'd still welcome a more general answer to the latter question.
tUpdate : {A : Set} (m : totalMap A) (x : String) (v : A) → totalMap A
tUpdate m x v = λ x' → (if (x == x') then v else m x')
Coq and Agda are both based on very roughly the same dependent type theory, so in theory it would be possible to take the proof term generated by a Coq script and translate it into an Agda program. However, there are many small (and not so small) differences, e.g. Coq's impredicative Prop, cumulativity, differences in the termination checkers, ect, that would make such a translation difficult or impossible.
However, what you're asking for here isn't really an automatic translator but rather a set of rules for translating Coq to Agda by hand. Since many basic features can be mapped one-to-one, this process is much more straightforward. However, any use of tactics in the Coq code you'll either have to translate to an explicit proof term in Agda or write your own Agda reflection macros (since there is no full tactic library for Agda yet).
To answer the specific problem you encountered here: Agda did not try to infer the return type of the tUpdate function because you already specified it to be Set yourself. If you want Agda to infer it for you, you can simply replace the return type with an underscore _ (which works fine in this case):
tUpdate : {A : Set} (m : totalMap A) (x : String) (v : A) → _
tUpdate m x v = λ x' → (if (x == x') then v else m x')

Is this formalization of the empty set correct in Agda?

I'm following The Haskell Road to Logic, Maths and Programming in Agda.
The book states:
The empty set is trivially a relation and is the smallest relation between two sets A and B
in Agda:
data ∅ : Set where
record ⊤ : Set where
record Σ (A : Set) (B : A → Set) : Set₁ where
constructor _,_
field
π₁ : A
π₂ : B π₁
_×_ : Set → Set → Set₁
A × B = Σ A (λ _ → B)
infixr 5 _×_ _,_
Relation : Set → Set₁
Relation P = P × P → Set
With that, I can define relations on specific sets:
lteℕ : Relation ℕ
lteℕ(x , y) = x ≤ℕ y where
_≤ℕ_ : ℕ → ℕ → Set
O ≤ℕ O = ⊤
O ≤ℕ S y = ⊤
S x ≤ℕ O = ∅
S x ≤ℕ S y = x ≤ℕ y
infixr 5 _≤ℕ_
But now I have a problem, because the signature for the empty set relation:
cannot be the empty set, since I already defined it as the unhabited type previously
results in the error Set₁ != Set when checking that the expression Set has type Set even when defined with a distinct symbol as Ø : Relation Set due to the necessity to avoid Russell's paradox in the language.
Is there a way around that that is still logically consistent? Thanks!
The answer depends on what you call a set. If by set you mean a representation of the mathematical sets, such as a list, then the empty set is just represented by the empty list.
If by set you mean the Agda Set which means a type, then the answer is a bit more complicated: there is not an empty type, but there are as many as you can think of. More precisely, there are as many empty types as data types for which you don't provide any constructor. The question is then more "which of these types do I chose to model the empty set ?" rather than "how do I model the empty set ?".
Here is an example of an agda module which emphasizes this aspect: First, I have a few imports and the header of my module:
open import Agda.Primitive
open import Data.Nat hiding (_⊔_)
module EmptySets where
Then I start by an empty type, the more simple you can think of:
data Empty : Set where
From this data type, it is possible to write an eliminator:
Empty-elim : ∀ {a} {A : Set a} → Empty → A
Empty-elim ()
This basically says that anything holds if Empty holds.
But, I could have also chosen to represent the empty set as the empty relation by defining a family of types, all empty, which are all relations. First, relations needs to be defined (I took the definition from the standard library):
REL : ∀ {a b} → Set a → Set b → (ℓ : Level) → Set (a ⊔ b ⊔ lsuc ℓ)
REL A B ℓ = A → B → Set ℓ
Then the family of empty relations can be defined :
data EmptyRelation {a b ℓ} {A : Set a} {B : Set b} : REL A B ℓ where
Since all these types are empty, they all provide an eliminator as well:
EmptyRelation-elim : ∀ {a b x ℓ} {A : Set a} {B : Set b} {X : Set x} {u : A} {v : B} → EmptyRelation {ℓ = ℓ} u v → X
EmptyRelation-elim ()
And, as a consequence, it is possible to instantiate this generic type to get a specific empty type, for instance, the empty relation over natural numbers, which never holds:
EmptyNaturalRelation : REL ℕ ℕ lzero
EmptyNaturalRelation = EmptyRelation
This is what is explained in the book: since a relation is a set of pairs, then the empty type is the smallest of this relation: the one where there are no pairs in it.
But you could also use predicates instead of relations, saying that the empty set is the smallest predicate over a given type: the one that never holds, in which case this is represented as the following:
Pred : ∀ {a} → Set a → (ℓ : Level) → Set (a ⊔ lsuc ℓ)
Pred A ℓ = A → Set ℓ
data EmptyPredicate {a ℓ} {A : Set a} : Pred A ℓ where
And you could be even crazier and decide to model the empty set as the following:
data EmptySomething {a} {A B C D E Z : Set a} : A → B → C → D → E → Z → Set where
All in all, there are no empty set in agda, but there are a potential infinity of empty types.
As for the code you presented in your question, there are several inaccuracies:
The relations are usually defined on two arguments instead of pairs of argument, which you can then curry on if needed to make them take a pair as parameter.
Why would you make lteℕ depend on _≤ℕ_ and not define it directly ?
You should define lteℕ as a data type rather than a function which returns either bottom or top, which will allow you to case-split on such a term in the future. Usually, this is defined this way (in the standard library):
data _≤_ : Rel ℕ 0ℓ where
z≤n : ∀ {n} → zero ≤ n
s≤s : ∀ {m n} (m≤n : m ≤ n) → suc m ≤ suc n

Law of excluded middle in Agda

I've heard the claim that Agda's Martin-Lof Type Theory with Excluded Middle is consistent. How would I go about adding it as a postulate? Also, after Adding LEM, is it then classical first-order logic? By this I mean, do I also have the not (for all) = there exist (not) equivalence? I don't know type theory, so please add additional explanation if you quote any results in type theory.
In MLTT, exists corresponds to a dependent pair which is defined in Data.Product in the standard library. It packages together the existence witness and the proof that it has the right property.
It is not necessary to postulate anything to prove that the negation of an existential statement implies the universal statement of the negated property:
∄⇒∀ : {A : Set} {B : A → Set} →
¬ (∃ λ a → B a) →
∀ a → ¬ (B a)
∄⇒∀ ¬∃ a b = ¬∃ (a , b)
To prove the converse however you do need the law of excluded middle to have a witness appear out of thin air. It is really easy to extend Agda with new postulates, you can simply write (Dec is defined in Relation.Nullary):
postulate LEM : (A : Set) → Dec A
It's always a good thing to remember how to prove double-negation elimination starting from LEM and we will need later on anyway so there it is (case_of_ is defined in Function and explained in README.Case):
¬¬A⇒A : {A : Set} → ¬ (¬ A) → A
¬¬A⇒A {A} ¬¬p =
case LEM A of λ
{ (yes p) → p
; (no ¬p) → ⊥-elim $ ¬¬p ¬p
}
And you can then prove that the negation of a universal statement implies an
existential one like so:
¬∀⇒∃ : {A : Set} {B : A → Set} →
¬ (∀ a → B a) →
∃ λ a → ¬ (B a)
¬∀⇒∃ {A} {B} ¬∀ =
case LEM (∃ λ a → ¬ B a) of λ
{ (yes p) → p
; (no ¬p) → ⊥-elim $ ¬∀ (¬¬A⇒A ∘ ∄⇒∀ ¬p)
}
A gist with all the right imports

Realising level polymorphic subsets within records

Using the notion of subsets as predicates,
ℙ : ∀ {b a} → Set a → Set (a ⊔ suc b)
ℙ {b} {a} X = X → Set b
I'd like to consider structures endowed with a predicate on subsets,
record SetWithAPredicate {a c} : Set {!!} where
field
S : Set a
P : ∀ {b} → ℙ {b} S → Set c
This is an ill-formed construction due to the level quantification used in ℙ. Everything works fine when I use S, P as parameters to a module, but I'd like them to be records so that I can form constructions on them and give instances of them.
I've tried a few other things, such as moving the level b of ℙ inside the definition via an existential but then that led to metavaraible trouble. I also tried changing the type of P,
P : ℙ {a} S → Set c
but then I can no longer ask for, say, the empty set to have the property:
P-⊥ : P(λ _ → ⊥)
This is not well typed since Set != Set a ---I must admit, I tried to use Level.lift here, but failed to do so.
More generally, this will also not allow me to express closure properties, such as P is closed under arbitrary unions ---this is what I'm really interested in.
I understand that I can just avoid level polymorphism,
ℙ' : ∀ {a} → Set a → Set (suc zero ⊔ a)
ℙ' {a} X = X → Set
but then simple items such as the largest subset,
ℙ'-⊤ : ∀ {i} {A : Set i} → ℙ' A
ℙ'-⊤ {i} {A} = λ e → Σ a ∶ A • a ≡ e
-- Σ_∶_•_ is just syntax for Σ A (λ a → ...)
will not even typecheck!
Perhaps I did not realise the notion of subset as predicate appropriately ---any advice would be appreciated. Thank-you!
You need to lift b out from P like this
record SetWithAPredicate {a c} b : Set {!!} where
field
S : Set a
P : ℙ {b} S → Set c
Yes, this is ugly and annoying, but that's how it's done in Agda (an example from standard library: _>>=_ is not properly universe polymorphic). Lift can help sometimes, but it quickly gets out of hand.
Perhaps I did not realise the notion of subset as predicate
appropriately ---any advice would be appreciated.
Your definition is correct, but there is another one, see 4.8.3 in Conor McBride's lecture notes.

Resources