New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Guardedness checker inconsistency with copatterns #1209
Comments
If termination checking was on sizes only, wit would not go through: {-# OPTIONS --sized-types --copatterns #-}
module _ where
open import Common.Size
record Stream (A : Set) {i : Size} : Set where
coinductive
field
head : A
tail : ∀{j : Size< i} → Stream A {j}
open Stream public
data Mu-Stream : Size → Set where
inn : ∀ {i} → Stream (Mu-Stream i) → Mu-Stream (↑ i)
wit : ∀{i} → Stream (Mu-Stream ∞) {i}
head (wit {i}) = inn (wit {∞})
tail (wit {i}) {j} = wit {j} Original comment by |
Original comment by
|
By playing around with test/fail/Issue1209.agda with Pierre Hyvernat, I found a -- Andreas, 2014-01-07 Issue reported by Dmitriy Traytel
-- Andreas, 2015-04-15 Issue resurrected with Pierre Hyvernat
{-# OPTIONS --copatterns #-}
module _ where
open import Common.Size
open import Common.Prelude
open import Common.Product
record Stream (A : Set) : Set where
coinductive
field
force : A × Stream A
open Stream
map : ∀{A B} → (A → B) → Stream A → Stream B
force (map f s) = let a , as = force s in f a , map f as
-- This type should be empty, as Stream A is isomorphic to ℕ → A.
data D : (i : Size) → Set where
lim : ∀ i → Stream (D i) → D (↑ i)
-- Emptiness witness for D.
empty : ∀ i → D i → ⊥
empty .(↑ i) (lim i s) = empty i (proj₁ (force s))
-- BAD: But we can construct an inhabitant.
inh : Stream (D ∞)
force inh = lim ∞ inh , inh -- Should be rejected by termination checker.
absurd : ⊥
absurd = empty ∞ (lim ∞ inh)
Original comment by
|
Same problem for musical coinduction open import Common.Coinduction renaming (∞ to Delay)
open import Common.Size
open import Common.Product
data ⊥ : Set where
record Stream (A : Set) : Set where
inductive
constructor delay
field
force : Delay (A × Stream A)
open Stream
head : ∀{A} → Stream A → A
head s = proj₁ (♭ (force s))
-- This type should be empty, as Stream A is isomorphic to ℕ → A.
data D : (i : Size) → Set where
lim : ∀ i → Stream (D i) → D (↑ i)
-- Emptiness witness for D.
empty : ∀ i → D i → ⊥
empty .(↑ i) (lim i s) = empty i (head s)
-- BAD: But we can construct an inhabitant.
inh : Stream (D ∞)
inh = delay (♯ (lim ∞ inh , inh)) -- Should be rejected by termination checker.
absurd : ⊥
absurd = empty ∞ (lim ∞ inh) Original comment by
|
See also https://lists.chalmers.se/pipermail/agda/2011/003339.html -- npouillard, 2011-10-04
open import Coinduction renaming (∞ to co)
open import Size
data ⊥ : Set where
data Mu-co : Size → Set where
inn : ∀ {i} → co (Mu-co i) → Mu-co (↑ i)
iter : ∀ {i} → Mu-co i → ⊥
iter (inn t) = iter (♭ t)
bla : Mu-co ∞
bla = inn (♯ bla)
false : ⊥
false = iter bla Original comment by |
This variant is due to Nisse, I think: {-# OPTIONS --copatterns #-}
open import Size
open import Data.Product
data ⊥ : Set where
record Delay (A : Set) : Set where
coinductive
constructor ♯
field ♭ : A × (⊥ → Delay A) -- Make it recursive to please termination checker
open Delay
data D : Size → Set where
inn : ∀ i → Delay (D i) → D (↑ i)
iter : ∀{i} → D i → ⊥
iter (inn i t) = iter (proj₁ (♭ t))
-- Should be rejected by termination checker
bla : Delay (D ∞)
♭ bla = inn ∞ bla , λ()
false : ⊥
false = iter (proj₁ (♭ bla)) Original comment by |
Version with mutual definition: {-# OPTIONS --copatterns #-}
open import Size
data ⊥ : Set where
mutual
data D : Size → Set where
inn : ∀ i → D' i → D (↑ i)
record D' (i : Size) : Set where
coinductive
constructor ♯
field ♭ : D i
open D'
iter : ∀{i} → D i → ⊥
iter (inn i t) = iter (♭ t)
-- Should be rejected by termination checker
bla : D' ∞
♭ bla = inn ∞ bla
false : ⊥
false = iter (♭ bla) Original comment by |
The symmetric version is correctly rejected, as coinductive projections are not size-preserving. Maybe we should just make inductive constructors not guardedness-preserving. {-# OPTIONS --copatterns #-}
open import Size
data ⊥ : Set where
mutual
data D (i : Size) : Set where
inn : D' i → D i
record D' (i : Size) : Set where
coinductive
field ♭ : {j : Size< i} → D j
open D'
bla : ∀{i} → D' i
♭ bla = inn bla
-- Should be rejected by termination checker
iter : D ∞ → ⊥
iter (inn t) = iter (♭ t)
false : ⊥
false = iter (♭ bla) Original comment by |
I guess this deserves the false label? |
Perhaps we could hide the old guardedness machinery under a flag:
We should reject the combination of |
I agree, the combination of |
I think the default should be something that we believe is safe, to avoid leading people astray. |
Blocked by #3451. |
I tried to fix this by (basically) replacing agda/src/full/Agda/Termination/TermCheck.hs Line 1048 in 94b9736
Is this all that is needed? The test suite points to a potential problem. For instance, take Lines 1 to 14 in 94b9736
The new error message does not include the problematic call to |
The standard library mixes the two forms of corecursion. For instance, |
Note also that |
Some further questions:
|
We could move the conversion functions to the |
I've pushed a fix now. Some notes:
|
Instead of waiting for a fix I pushed a test case to |
@andreasabel, consider the following code: Type : Set
postulate
type : Type
Term : Type → Set
Type = Term type When I run Agda with
This looks strange to me. Why are there calls from |
I'm moving the discussion of the potential problem discussed in the previous comment to #1556. |
Your fix as described in #1209 (comment) LGTM, @nad. |
Bug found by Dmitriy Traytel.
It is a bug in the untyped guardedness check.
Since (shd wit) is not a recursive position for streams, the recursive call to
wit should be banned here. Only (stl wit) is a recursive position.
Original issue reported on code.google.com by
andreas....@gmail.com
on 19 Jun 2014 at 6:46The text was updated successfully, but these errors were encountered: