--copatterns
is now on by default. To switch off
parsing of copatterns, use: {-# OPTIONS --no-copatterns #-}
--rewriting
is now needed to use REWRITE
pragmas and
rewriting during reduction. Rewriting is not --safe
.To use rewriting, first specify a relation symbol R
that will
later be used to add rewrite rules. A canonical candidate would be
propositional equality
{-# BUILTIN REWRITE _≡_ #-}
but any symbol R
of type Δ → A → A → Set i
for some A
and i
is accepted. Then symbols q
can be added to rewriting provided
their type is of the form Γ → R ds l r
. This will add a rewrite
rule
Γ ⊢ l ↦ r : A[ds/Δ]
to the signature, which fires whenever a term is an instance of l
.
For example, if
plus0 : ∀ x → x + 0 ≡ x
(ideally, there is a proof for plus0
, but it could be a
postulate), then
{-# REWRITE plus0 #-}
will prompt Agda to rewrite any well-typed term of the form t + 0
to t
.
Some caveats: Agda accepts and applies rewrite rules naively, it is very easy to break consistency and termination of type checking. Some examples of rewrite rules that should not be added:
refl : ∀ x → x ≡ x -- Agda loops
plus-sym : ∀ x y → x + y ≡ y + x -- Agda loops
absurd : true ≡ false -- Breaks consistency
Adding only proven equations should at least preserve consistency, but this is only a conjecture, so know what you are doing! Using rewriting, you are entering into the wilderness, where you are on your own!
forall
/ ∀
now parses like λ
, i.e., the following parses now
[Issue #1583]: ⊤ × ∀ (B : Set) → B → B
_
can now also stand for an inaccessible
pattern (dot pattern). This alleviates the need for writing ._
.
[Issue #1605] Instead of transVOld : ∀{A : Set} (a b c : A) → a ≡ b → b ≡ c → a ≡ c
transVOld _ ._ ._ refl refl = refl
one can now write
transVNew : ∀{A : Set} (a b c : A) → a ≡ b → b ≡ c → a ≡ c
transVNew _ _ _ refl refl = refl
and let Agda decide where to put the dots. This was always possible by using hidden arguments
transH : ∀{A : Set}{a b c : A} → a ≡ b → b ≡ c → a ≡ c
transH refl refl = refl
which is now equivalent to
transHNew : ∀{A : Set}{a b c : A} → a ≡ b → b ≡ c → a ≡ c
transHNew {a = _}{b = _}{c = _} refl refl = refl
Before, underscore _
stood for an unnamed variable that could not
be instantiated by an inaccessible pattern. If one no wants to
prevent Agda from instantiating, one needs to use a variable name
other than underscore (however, in practice this situation seems
unlikely).
The following example type-checks now:
open import Common.Size
-- List should be monotone in both arguments
-- (even when `cons' is missing).
data List (i : Size) (A : Set) : Set where
[] : List i A
castLL : ∀{i A} → List i (List i A) → List ∞ (List ∞ A)
castLL x = x
-- Stream should be antitone in the first and monotone in the second argument
-- (even with field `tail' missing).
record Stream (i : Size) (A : Set) : Set where
coinductive
field
head : A
castSS : ∀{i A} → Stream ∞ (Stream ∞ A) → Stream i (Stream i A)
castSS x = x
SIZELT
lambdas must be consistent
[Issue #1523, see Abel
and Pientka, ICFP 2013]. When lambda-abstracting over type (Size<
size
) then size
must be non-zero, for any valid instantiation of
size variables.
data Nat (i : Size) : Set where
zero : ∀ (j : Size< i) → Nat i
suc : ∀ (j : Size< i) → Nat j → Nat i
{-# TERMINATING #-}
-- This definition is fine, the termination checker is too strict at the moment.
fix : ∀ {C : Size → Set}
→ (∀ i → (∀ (j : Size< i) → Nat j -> C j) → Nat i → C i)
→ ∀ i → Nat i → C i
fix t i (zero j) = t i (λ (k : Size< i) → fix t k) (zero j)
fix t i (suc j n) = t i (λ (k : Size< i) → fix t k) (suc j n)
The λ (k : Size< i)
is fine in both cases, as context
i : Size, j : Size< i
guarantees that i
is non-zero.
record Stream {i : Size} (A : Set) : Set where
coinductive
constructor _∷ˢ_
field
head : A
tail : ∀ {j : Size< i} → Stream {j} A
open Stream public
_++ˢ_ : ∀ {i A} → List A → Stream {i} A → Stream {i} A
[] ++ˢ s = s
(a ∷ as) ++ˢ s = a ∷ˢ (as ++ˢ s)
This fails, maybe unjustified, at
i : Size, s : Stream {i} A
⊢
a ∷ˢ (λ {j : Size< i} → as ++ˢ s)
Fixed by defining the constructor by copattern matching:
record Stream {i : Size} (A : Set) : Set where
coinductive
field
head : A
tail : ∀ {j : Size< i} → Stream {j} A
open Stream public
_∷ˢ_ : ∀ {i A} → A → Stream {i} A → Stream {↑ i} A
head (a ∷ˢ as) = a
tail (a ∷ˢ as) = as
_++ˢ_ : ∀ {i A} → List A → Stream {i} A → Stream {i} A
[] ++ˢ s = s
(a ∷ as) ++ˢ s = a ∷ˢ (as ++ˢ s)
fix : ∀ {C : Size → Set}
→ (∀ i → (∀ (j : Size< i) → C j) → C i)
→ ∀ i → C i
fix t i = t i λ (j : Size< i) → fix t j
For i=0
, there is no such j
at runtime, leading to looping
behavior.
record Cont : Set₁ where
constructor _◃_
field
Sh : Set
Pos : Sh → Set
open Cont
data W (C : Cont) : Set where
sup : (s : Sh C) (k : Pos C s → W C) → W C
bogus : {C : Cont} → W C → Set
bogus w = {!w!}
Case splitting on w
yielded, since the fix of
Issue #473,
bogus {Sh ◃ Pos} (sup s k) = ?
Now it gives, as expected,
bogus (sup s k) = ?
Issues fixed (see bug tracker):
#1546 (copattern matching and with-clauses)
#1560 (positivity checker inefficiency)
#1584 (let pattern with trailing implicit)