[Agda] multiple instance resolution and negation

Guillaume Brunerie guillaume.brunerie at gmail.com
Sat Aug 29 14:34:19 CEST 2020


Hi Marcus,

A better way of preventing a definition to reduce is to use a record:


record NonNegative (x : X) : Set where
  constructor NonNegative-in
  field
    NonNegative-out : 0 ≤ x


This way you get that `NonNegative x` does not reduce to anything, so
you can use it as an instance argument without issues, but at the same
time it is still equivalent to `0 ≤ x` via the two functions
NonNegative-in and NonNegative-out (which are definitionally inverse
to each other).
You could also directly define _≤_ as a record whose only field has
the definition you currently have as its type, so that it doesn’t
reduce to a function type (although I have a feeling that a more
specialized type class like NonNegative might be better).

Best,
Guillaume

Den lör 29 aug. 2020 kl 13:50 skrev Marcus Christian Lehmann
<lehmann at tet.tu-berlin.de>:
>
> For everyone with a similar problem:
>
> I found that using an identity function `!_` declared in an `abstract` block
>
>    abstract
>      !_ : ∀{ℓ} {X : Type ℓ} → X → X
>      ! x = x
>
> does the trick of "blocking" Agda's instance inspection. Within that
> `abstract` block it is possible to proof
>
>    !-≡ : ∀{ℓ} {X : Type ℓ} → (! X) ≡ X
>    !-≡ = refl
>
> which can be used to define
>
>    !!_ : ∀{ℓ} {X : Type ℓ} → X → ! X
>    !!_ {X = X} x = transport (sym (!-≡ {X = X})) x
>
> I've assembled a minimal example how this works and I hope this instance
> resolution behavior does not change in the future.
>
> kind regards,
> Christian
>
> EXAMPLE:
>
> {-# OPTIONS --cubical --no-import-sorts #-}
>
> module Test3 where
>
> open import Cubical.Foundations.Everything renaming (_⁻¹ to _⁻¹ᵖ; assoc
> to ∙-assoc)
> open import Cubical.Foundations.Logic
>
> abstract
>    !_ : ∀{ℓ} {X : Type ℓ} → X → X
>    ! x = x
>
>    !-≡ : ∀{ℓ} {X : Type ℓ} → (! X) ≡ X
>    !-≡ = refl -- makes use of the definition of `!_` within this block
>
>    !!_ : ∀{ℓ} {X : Type ℓ} → X → ! X
>    !!_ {X = X} x = transport (sym (!-≡ {X = X})) x
>
>    !!⁻¹_ : ∀{ℓ} {X : Type ℓ} → ! X → X
>    !!⁻¹_ {X = X} x = transport (!-≡ {X = X}) x
>
>    infix 1 !_
>    infix 1 !!_
>    infix 1 !!⁻¹_
>
> -- !-≡' : ∀{ℓ} {X : Type ℓ} → (! X) ≡ X
> -- !-≡' = refl -- cannot make use of the definition of `!_` anymore
>
> hPropRel : ∀ {ℓ} (A B : Type ℓ) (ℓ' : Level) → Type (ℓ-max ℓ (ℓ-suc ℓ'))
> hPropRel A B ℓ' = A → B → hProp ℓ'
>
> module TestB {ℓ ℓ'} (X : Type ℓ)
>               (0ˣ : X) (_+_ _·_ : X → X → X) (_<_ : hPropRel X X ℓ')
>               (let infixl 5 _+_; _+_ = _+_) where
>
>    _≤_ : hPropRel X X ℓ'
>    x ≤ y = ¬(y < x)
>
>    postulate
>      sqrt : (x : X) → {{ ! [ 0ˣ ≤ x ] }} → X
>      0≤x² : ∀ x → [ 0ˣ ≤ (x · x) ]
>
>    instance -- module-scope instances
>      _ = λ {x} → !! 0≤x² x
>
>    test4 : (x y z : X) → [ 0ˣ ≤ x ] → [ 0ˣ ≤ y ] → X
>    test4 x y z 0≤x 0≤y =
>      let instance -- let-scope instances
>            _ = !! 0≤x
>            _ = !! 0≤y
>            _ = !! 0≤x² x -- preferred over the instance from module-scope
>      in ( (sqrt x)       -- works
>         + (sqrt y)       -- also works
>         + (sqrt (z · z)) -- uses instance from module scope
>         + (sqrt (x · x)) -- uses instance from let-scope (?)
>         )
>
> _______________________________________________
> Agda mailing list
> Agda at lists.chalmers.se
> https://lists.chalmers.se/mailman/listinfo/agda


More information about the Agda mailing list