extending or inferring (PID / UFD) in a Lean class definition - typeclass

Why is mathlib's definition of UFD this:
class unique_factorization_domain (α : Type*) [integral_domain α] :=
(factors : α → multiset α)
(factors_prod : ∀{a : α}, a ≠ 0 → (factors a).prod ~ᵤ a)
(prime_factors : ∀{a : α}, a ≠ 0 → ∀x∈factors a, prime x)
(asking for the integral domain structure to be inferred by type class inference) but its definition of PID is this:
class principal_ideal_domain (α : Type*) extends integral_domain α :=
(principal : ∀ (S : ideal α), S.is_principal)
extending the integral domain structure? What is the difference? Does the old structure command have something to do with it?

My impression from the discussion on the Lean chat is that for subtle reasons related to type class inference it is probably better to extend the class, and so perhaps the definition of UFD needs to be refactored.

Related

What axiom makes you be able to skip definition for impossible input for function in Agda?

_/_ : (dividend divisor : ℕ) .{{_ : NonZero divisor}} → ℕ
m / (suc n) = div-helper 0 n m n
In this function definition, there is no definition of case when second input is zero, because Agda knows second input cannot be zero. But in formal(theoretical) perspective, what justify these function definition? Is there axioms like 'you can skip definition for impossible input' in Type Theory, like axiom J and axiom K?
The axiom that you need is called the "principle of explosion" or "ex falso quodlibet" (see https://en.wikipedia.org/wiki/Principle_of_explosion). In type theory, this is typically formulated as an elimination principle for the empty type:
A : Type b : ⊥
————————————————–
absurd b : A

Parametric theorem implied by goal

During some development using cubical-agda, I noticed (and later checked) that my current goal, if proven would also imply such theorem:
parametric? : ∀ ℓ → Type (ℓ-suc ℓ)
parametric? ℓ = (f : {A : Type ℓ} → List A ≃ List A)
→ (A : Type ℓ) → length ∘ equivFun (f {A}) ≡ length
I suspect that this is example of parametric theorem, which is true, but is unprovable in cubical agda. Is it the case?
Can I safely assume that my current goal is also unprovable?
Yes, because it's false in the standard (simplicial sets) model.
If excluded middle holds, we can define f : {A : Type ℓ} → List A ≃ List A by first doing a case analysis on whether A is contractible or not. If A is not contractible, f gives the identity equivalence, but if A is contractible, then List A is equivalent to Nat, and, f can give an equivalence that, e.g., permutes odds and evens.

How to go from an explicit proof of size decrease to a halting reduction algorithm?

Suppose I have:
A Linear : Set type for linear λ-calculus terms.
A reduce-once : Term → Term function that performs a global reduction of redexes.
A size : Linear → Nat relation that counts the number of constructors.
A proof reduce-once-halts : (t : Linear) → size (reduce-once t) < size t.
That is, I have a proof that applying reduce-once always decreases the size of a term. From that, one should logically be able to implement a terminating function, reduce : (t : Linear) → Sigma t IsNormalized, that reduces the term to normal form. Since I believe this is a common situation, my question is: how is that usually formalized in Agda? How can I convince it that a function that decreases the size of its argument can be applied recursively and will eventually halt?
You can use <-rec from the Data.Nat.Induction module to do well-founded induction over _<_. In this case, one solution is to do induction on the predicate "terms of size strictly less than n can be reduced":
open import Data.Nat
open import Data.Nat.Induction
open import Data.Nat.Properties
open import Relation.Binary.PropositionalEquality
postulate
Term : Set
reduce-once : Term → Term
size : Term → ℕ
reduce-once-halts : (t : Term) → size (reduce-once t) < size t
reduce-aux : (n : ℕ) (t : Term) → size t < n → Term
reduce-aux = <-rec
(λ n → (t : Term) → size t < n → Term)
λ n h t size-t<n → h (size t) size-t<n (reduce-once t) (reduce-once-halts t)
reduce : Term → Term
reduce t = reduce-aux (1 + size t) t ≤-refl

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.

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.

Resources