agda / agda

Agda is a dependently typed programming language / interactive theorem prover.

Home Page:https://wiki.portal.chalmers.se/agda/pmwiki.php

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Agda always has irrelevant projections

dolio opened this issue · comments

A question on zulip led me to realize that you can always produce irrelevant projections from a record. For example:

record  : Set where

record TSquash (A : Set) : Set where
  field
    .extract :-> A

  .tflat :-> A
  tflat x = extract x

open TSquash

.flat : {A}  .A -> A
flat a = tflat (λ where .extract _  a) _

That passes the latest Agda without --irrelevant-projections.

I think the issue is that tflat is accepted as long as it is eta expanded (but properly rejected if reduced, which was the original zulip question). I don't know what that becomes internally, but it seems strange to accept it unless --irrelevant-projections is on.

BTW, this is inconsistent with cubical:

open import Cubical.Foundations.Prelude
open import Cubical.Data.Bool
open import Cubical.Data.Empty
open import Cubical.Data.Unit
open import Cubical.Relation.Nullary


variable
  A B : Type

record TSquash (A : Type) : Type where
  field .extract : Unit -> A

  .tflat : Unit -> A
  tflat x = extract x

open TSquash

emb : A -> TSquash A
emb a .extract _ = a

lemma₀ :  t  PathP (λ i  TSquash (notEq i)) t t
lemma₀ t i = transport (λ j  TSquash (notEq (i ∧ j))) t

lemma₁ : ¬ ( A  TSquash A -> A)
lemma₁ ext = not≢const (ext Bool f) sublemma where
  f = emb false

  sublemma : not (ext Bool f) ≡ ext Bool f
  sublemma = fromPathP λ i  ext (notEq i) (lemma₀ f i)

.ext : TSquash A -> A
ext t = tflat t _

.xplode : ⊥
xplode = lemma₁ (λ _  ext)

bad : ⊥
bad = e xplode where
  e : .⊥ -> ⊥
  e ()

Proposed fix: forbid (even irrelevant) definitions in records to use irrelevant fields unless --irrelevant-projections is on.

I'm not sure that's good enough due to #6359. E.G. you can do this:

open import Cubical.Foundations.Prelude
open import Cubical.Data.Bool
open import Cubical.Data.Empty
open import Cubical.Relation.Nullary

variable
  A B : Type

record TSquash (A : Type) : Type where
  constructor emb
  field .extract : A

lemma₀ :  t  PathP (λ i  TSquash (notEq i)) t t
lemma₀ t i = transport (λ j  TSquash (notEq (i ∧ j))) t

lemma₁ : ¬ ( A  TSquash A -> A)
lemma₁ ext = not≢const (ext Bool f) sublemma where
  f = emb false

  sublemma : not (ext Bool f) ≡ ext Bool f
  sublemma = fromPathP λ i  ext (notEq i) (lemma₀ f i)

lemma₂ : ¬ ( A  .A -> A)
lemma₂ f = lemma₁ λ A (emb x)  f A x

bad : ⊥
bad = e (lemma₂ λ A x  let open TSquash (emb x) in extract) where
  e : .⊥ -> ⊥
  e ()

Unless what you're talking about affects opening as well. This has no irrelevant definitions.

BTW, emb being a constructor is unnecessary, too.

Would fixing this (via @andreasabel 's proposal, or otherwise) invalidate agda/agda-stdlib#2199 and/or agda/agda-stdlib#2243 ?
I would be good to know before I commit to doing any more work on either of those!

My understanding is that the proposal is only to restrict definitions like:

.foo : ...
foo = ...

where foo itself is irrelevant. Not every definition that has irrelevance in the type. So it looks like your work there would be unaffected.

However, I don't know what a fix to the other example would entail. I guess even the most brute force option might be, 'you can't open (applied) record modules with irrelevant fields without --irrelevant-projections.' But that also doesn't affect your work, right?