Open nad opened 10 months ago
Agda rejects the following code:
{-# OPTIONS --safe --cubical-compatible --erasure #-}
data _≡_ {@0 a} {@0 A : Set a} (@0 x : A) : A → Set a where
refl : x ≡ x
x ≡ x is not usable at the required modality @ω
when checking the constructor refl in the declaration of _≡_
However, the following pieces of code are allowed:
{-# OPTIONS --safe --cubical-compatible --erasure #-}
data _≡′_ {@0 a} {@0 A : Set a} (x : A) : @0 A → Set a where
refl : x ≡′ x
{-# OPTIONS --safe --cubical-compatible --erasure #-}
data _≡″_ {@0 a} {@0 A : Set a} (@0 x : A) : @0 A → Set a where
refl : x ≡″ x
I experimented a little with these definitions. One can currently prove that x ≡′ y
and x ≡″ y
are equivalent to [ x ] ≡ [ y ]
(without any warnings):
{-# OPTIONS
--safe --cubical-compatible --erasure --hidden-argument-puns #-}
open import Agda.Builtin.Equality
open import Agda.Primitive
private variable
a p : Level
A : Set a
x y z : A
------------------------------------------------------------------------
-- Some definitions related to the builtin equality type
-- The J rule. This is the only definition in this file that matches
-- directly on refl for _≡_.
J :
∀ {@0 a} {@0 A : Set a} {x y : A}
(P : (y : A) → x ≡ y → Set p) →
P x refl →
(eq : x ≡ y) →
P y eq
J _ p refl = p
-- Substitutivity.
subst :
∀ {@0 a} {@0 A : Set a} {x y : A}
(P : A → Set p) → x ≡ y → P x → P y
subst P eq p = J (λ x _ → P x) p eq
-- Transitivity.
trans : x ≡ y → y ≡ z → x ≡ z
trans {x} eq₁ eq₂ = subst (λ y → x ≡ y) eq₂ eq₁
------------------------------------------------------------------------
-- Erased
-- A definition of Erased without definitional η-equality.
data Erased {@0 a} (@0 A : Set a) : Set a where
[_] : @0 A → Erased A
-- A projection.
@0 erased : Erased A → A
erased [ x ] = x
-- Propositional η-expansion.
η : ∀ {@0 a} {@0 A : Set a} {x : Erased A} → x ≡ [ erased x ]
η {x = [ _ ]} = refl
------------------------------------------------------------------------
-- An alternative definition of equality
-- Note that all arguments are erased except for the last parameter.
-- Everything still works if this parameter is made erased.
data _≡′_ {@0 a} {@0 A : Set a} (x : A) : @0 A → Set a where
refl : x ≡′ x
-- The J rule. This is the only definition in this file that matches
-- directly on refl for _≡′_.
J′ :
∀ {@0 a} {@0 A : Set a} {@0 x y : A}
(P : (@0 y : A) → x ≡′ y → Set p) →
P x refl →
(eq : x ≡′ y) →
P y eq
J′ _ p refl = p
-- Substitutivity.
subst′ :
∀ {@0 a} {@0 A : Set a} {@0 x y : A}
(P : @0 A → Set p) → x ≡′ y → P x → P y
subst′ P eq p = J′ (λ x _ → P x) p eq
-- A lemma used to implement []-injective′.
cong-erased′ :
{@0 A : Set a} {x : A} {@0 y : Erased A} →
[ x ] ≡′ y → x ≡′ erased y
cong-erased′ {x} eq = subst′ (λ y → x ≡′ erased y) eq refl
-- The constructor [_] is injective up to _≡′_.
[]-injective′ :
{@0 A : Set a} {x : A} {@0 y : A} →
[ x ] ≡′ [ y ] → x ≡′ y
[]-injective′ = cong-erased′
------------------------------------------------------------------------
-- Converting between _≡_ and _≡′_
-- One can convert directly from _≡_ to _≡′_.
≡→≡′ : {@0 A : Set a} {x y : A} → x ≡ y → x ≡′ y
≡→≡′ {x} eq = subst (λ y → x ≡′ y) eq refl
-- There is a bijective correspondence between x ≡′ y and
-- [ x ] ≡ [ y ].
to : {@0 A : Set a} {@0 x y : A} → x ≡′ y → [ x ] ≡ [ y ]
to {x} eq = subst′ (λ y → [ x ] ≡ [ y ]) eq refl
from : {@0 A : Set a} {x : A} {@0 y : A} → [ x ] ≡ [ y ] → x ≡′ y
from eq = []-injective′ (≡→≡′ eq)
from-to :
{@0 A : Set a} {x : A} {@0 y : A}
(eq : x ≡′ y) → from (to eq) ≡ eq
from-to = J′ (λ y eq → from (to eq) ≡ eq) refl
to-from :
{@0 A : Set a} {x : A} {@0 y : A}
(eq : [ x ] ≡ [ y ]) → to (from eq) ≡ eq
to-from = lemma
where
lemma :
{@0 A : Set a} {x : A} {y : Erased A}
(eq : [ x ] ≡ y) →
subst′ (λ y → [ x ] ≡ [ y ]) (cong-erased′ (≡→≡′ eq)) refl ≡
trans eq η
lemma {x} =
J (λ y eq →
subst′ (λ y → [ x ] ≡ [ y ]) (cong-erased′ (≡→≡′ eq)) refl ≡
trans eq η)
refl
Hopefully it is not possible to prove that x ≡′ y
(or x ≡″ y
) implies x ≡ y
, because then the type [ x ] ≡ [ y ] → x ≡ y
would be inhabited.
One can perhaps fix this problem temporarily by making the
UnsupportedIndexedMatch
warning incompatible with--safe
, and also incompatible with compilation. However, note that this warning is not raised when--without-K
is used. There is a check that is intended to make sure that code that is accepted when--without-K
is used is also accepted when--cubical-compatible
is used. If that check can be extended so thatbad
is rejected, then the check can perhaps be used also for the other options (--cubical-compatible
,--erased-cubical
and--cubical
).
What do you think, should we make UnsupportedIndexedMatch
incompatible with --safe
and compilation?
This is not a regression, so it can wait until the next release.
I discovered that erasure is still (#4784) not compatible with (erased) univalence and []-cong.
The following code should not be allowed:
The code should still be rejected if
--cubical-compatible
is replaced by--without-K
,--erased-cubical
or--cubical
.If this code is allowed, then one can construct a boolean that is provably equal to false but compiled to (more or less) true:
The code uses some postulates, but I expect that all the postulates except for
putStrLn
can be implemented.Note that Agda complains about
bad
:I suspect that (for options other than
--without-K
) the problem is that Agda does not generate any extra clauses forbad
: hopefully the generated clauses would be rejected by Agda. One can perhaps fix this problem temporarily by making theUnsupportedIndexedMatch
warning incompatible with--safe
, and also incompatible with compilation. However, note that this warning is not raised when--without-K
is used. There is a check that is intended to make sure that code that is accepted when--without-K
is used is also accepted when--cubical-compatible
is used. If that check can be extended so thatbad
is rejected, then the check can perhaps be used also for the other options (--cubical-compatible
,--erased-cubical
and--cubical
).