How to do a rewrite in a premise? - agda

Any-comm : ∀ {A : Set} {P : A → Set} (xs ys : List A) →
Any P (xs ++ ys) → Any P (ys ++ xs)
Any-comm xs [] prf = {!!}
Goal: Any P xs
————————————————————————————————————————————————————————————
prf : Any P (xs ++ [])
xs : List A
P : A → Set (not in scope)
A : Set (not in scope)
How do I rewrite prf with the append identity here? I suppose I could rewrite the goal to match instead, but would it be possible to do the same in the premise? I feel the later would be more neat.

Ah, it seems my assumption of how rewrite works was wrong.
Any-comm xs [] prf rewrite sym (++-identityʳ xs) = {!!}
Goal: Any P (xs ++ [])
————————————————————————————————————————————————————————————
prf : Any P ((xs ++ []) ++ [])
P : A → Set (not in scope)
xs : List A
A : Set (not in scope)
When I tried the above I was surprised to see it rewrite both the goal and the premise. So from that the way to rewrite the premise is.
Any-comm xs [] prf rewrite ++-identityʳ xs = prf
I am not sure if this is supposed to be so surprising, but I had not noticed this despite nearly going through the entirety of vol 1 of the PLFA book. This behavior is different from Coq's rewrite.

Related

Agda: std-lib: List: pattern matching with snoc

I wrote a function to get everything but the last element of a List from std-lib:
open import Data.List
allButLast : ∀ {a} {A : Set a} → List A → List A
allButLast [] = []
allButLast (x ∷ []) = []
allButLast (x ∷ xs) = x ∷ allButLast xs
For proof purposes, I would like to rewrite this function using ∷ʳ instead:
allButLast2 : ∀ {a} {A : Set a} → List A → List A
allButLast2 [] = []
allButLast2 (xs ∷ʳ x) = xs
but I'm getting this error:
Could not parse the left-hand side allButLast2 (xs ∷ʳ x)
Operators used in the grammar:
v.∷ʳ (infixl operator, level 5) [_∷ʳ_ (/Users/fss/Dropbox/Documents/projects/Coding/dev/agda/agda-stdlib-1.4/src/Data/Vec/Base.agda:275,1-5)]
∷ʳ (infixl operator, level 6) [_∷ʳ_ (/Users/fss/Dropbox/Documents/projects/Coding/dev/agda/agda-stdlib-1.4/src/Data/List/Base.agda:351,1-5)]
when scope checking the left-hand side allButLast2 (xs ∷ʳ x) in
the definition of allButLast2
I don't understand why it can't parse the left hand side of
allButLast2 (xs ∷ʳ x) = xs
The _∷ʳ_ operator is a function, not a constructor or a pattern synonym, so it can't be used in a pattern:
infixl 6 _∷ʳ_
_∷ʳ_ : List A → A → List A
xs ∷ʳ x = xs ++ [ x ]

Eliminating erased argument with only one valid case

I have defined infinite streams as follows:
record Stream (A : Set) : Set where
coinductive
field head : A
field tail : Stream A
and an inductive type which shows that some element in a stream eventually satisfies a predicate:
data Eventually {A} (P : A -> Set) (xs : Stream A) : Set where
here : P (head xs) -> Eventually P xs
there : Eventually P (tail xs) -> Eventually P xs
I would like to write a function which skips over elements of the stream until the head of the stream satisfies a predicate. To ensure termination, we must know that an element eventually satisfies the predicate, else we could loop forever. Hence, the definition of Eventually must be passed as an argument. Furthermore, the function should not computationally depend on the Eventually predicate, as it is just there to prove termination, so I would like it to be an erased argument.
dropUntil : {A : Set} {P : A -> Set} (decide : ∀ x → Dec (P x)) → (xs : Stream A) → #0 Eventually P xs → Stream A
dropUntil decide xs ev with decide (head xs)
... | yes prf = xs
... | no contra = dropUntil decide (tail xs) ?
Here is the problem - I would like to fill in the hole in the definition. From contra in scope, we know that the head of the stream does not satisfy P, and hence by definition of eventually, some element in the tail of the stream must satisfy P. If Eventually wasn't erased in this context, we could simply pattern match on the predicate, and prove the here case impossible. Normally in these scenarios I would write an erased auxiliary function, on the lines of:
#0 eventuallyInv : ∀ {A} {P : A → Set} {xs : Stream A} → Eventually P xs → ¬ P (head xs) → Eventually P (tail xs)
eventuallyInv (here x) contra with contra x
... | ()
eventuallyInv (there ev) contra = ev
The problem with this approach is that the Eventually proof is the structurally recursive argument in dropUntil, and calling this auxiliary function does not pass the termination checker as Agda does not "look inside" the function definition.
Another approach I tried is inlining the above erased function into the definition of dropUntil. Unfortunately, I had no luck with this approach either - using the definition of case ... of like described here https://agda.readthedocs.io/en/v2.5.2/language/with-abstraction.html did not pass the termination checker either.
I have written an equivalent program in Coq which is accepted (using Prop rather than erased types), so I am confident that my reasoning is correct. The main reason why Coq accepted the definition and Agda doesn't is that Coq's termination checker expands function definitions, and hence the "auxiliary erased function" approach succeeds.
EDIT:
This is my attempt using sized types, however it does not pass the termination checker and I can't figure out why.
record Stream (A : Set) : Set where
coinductive
field
head : A
tail : Stream A
open Stream
data Eventually {A} (P : A → Set) (xs : Stream A) : Size → Set where
here : ∀ {i} → P (head xs) → Eventually P xs (↑ i)
there : ∀ {i} → Eventually P (tail xs) i → Eventually P xs (↑ i)
#0 eventuallyInv : ∀ {A P i} {xs : Stream A} → Eventually P xs (↑ i) → ¬ P (head xs) → Eventually P (tail xs) i
eventuallyInv (here p) ¬p with ¬p p
... | ()
eventuallyInv (there ev) ¬p = ev
dropUntil : ∀ {A P i} → (∀ x → Dec (P x)) → (xs : Stream A) → #0 Eventually P xs (↑ i) → Stream A
dropUntil decide xs ev with decide (head xs)
... | yes p = xs
... | no ¬p = dropUntil decide (tail xs) (eventuallyInv ev ¬p)
In your case you can work with a weaker notion of Eventually which matches what dropUntil actually needs to know. It's also single constructor so you can match on it even when erased.
data Eventually' {A} (P : A -> Set) (xs : Stream A) : Set where
next : (¬ P (head xs) → Eventually' P (tail xs)) → Eventually' P xs
eventuallyInv : ∀ {A} {P : A → Set} {xs : Stream A} → (ev : Eventually P xs) → Eventually' P xs
eventuallyInv (here p) = next \ np → ⊥-elim (np p)
eventuallyInv (there ev) = next \ np → eventuallyInv ev
dropUntil' : {A : Set} {P : A -> Set} (decide : ∀ x → Dec (P x)) → (xs : Stream A) → #0 Eventually' P xs → Stream A
dropUntil' decide xs (next ev) with decide (head xs)
... | yes prf = xs
... | no contra = dropUntil' decide (tail xs) (ev contra)
dropUntil : {A : Set} {P : A -> Set} (decide : ∀ x → Dec (P x)) → (xs : Stream A) → #0 Eventually P xs → Stream A
dropUntil decide xs ev = dropUntil' decide xs (eventuallyInv ev)

With expression non evaluation

I am trying to define a CoList without the delay constructors. I am running into a problem where I use a with expression but agda doesn't refine the type of a subcase.
module Failing where
open import Data.Unit
open import Data.Empty
open import Data.Maybe
open import Data.Nat
open import Data.Vec hiding (head ; tail ; map ; take)
record CoList (A : Set) : Set where
coinductive
field
head : Maybe A
tail : maybe (λ _ → ⊤) ⊥ head -> CoList A
open CoList
nil : ∀ {A} -> CoList A
head nil = nothing
tail nil ()
cons : ∀ {A} -> A -> CoList A -> CoList A
head (cons x xs) = just x
tail (cons x xs) tt = xs
take : ∀ {A} -> CoList A -> (n : ℕ) -> Maybe (Vec A n)
take l zero = just []
take l (suc n) with head l
... | nothing = nothing
... | just x = map (λ xs → x ∷ xs) (take (tail l {!!}) n)
The type of that hole is maybe (λ _ → ⊤) ⊥ (head l) but because of the with expression I would expect the type to be ⊤. I expect this because I withed on the head l and in that case head l = just x. If I try to fill the whole with tt agda mode gives me the following error:
⊤ !=< (maybe (λ _ → ⊤) ⊥ (head l)) of type Set
when checking that the expression tt has type
(maybe (λ _ → ⊤) ⊥ (head l))
I answered the question below, so now I am curious is there a better way to encode this list without the delay constructor?
You can think of with t as replacing t by whatever you match against, in the types of both function arguments and the goal. However, head l does not appear in your goal type when you perform the with — a goal whose type involves head l only appears later, once you have partially constructed the solution. This is the reason why your initial attempt doesn't work.
The inspect idiom, as demonstrated in your answer, is indeed the usual solution for this sort of problem.
As for encodings of coinductive types with 'more than one constructor', there are two (closely related) approaches that I'm aware of:
A mutual inductive/coinductive type:
data CoList′ (A : Set) : Set
record CoList (A : Set) : Set
data CoList′ A where
[] : CoList′ A
_∷_ : A → CoList A → CoList′ A
record CoList A where
coinductive
field
unfold : CoList′ A
open CoList
repeat : ∀ {A} → A → CoList A
repeat x .unfold = x ∷ repeat x
take : ∀ {A} → ℕ → CoList A → List A
take zero _ = []
take (suc n) xs with unfold xs
... | [] = []
... | x ∷ xs′ = x ∷ take n xs′
Taking the cofixpoint explicitly:
data CoList′ (A : Set) (CoList : Set) : Set where
[] : CoList′ A CoList
_∷_ : A → CoList → CoList′ A CoList
record CoList (A : Set) : Set where
coinductive
field
unfold : CoList′ A (CoList A)
open CoList
repeat : ∀ {A} → A → CoList A
repeat x .unfold = x ∷ repeat x
take : ∀ {A} → ℕ → CoList A → List A
take zero _ = []
take (suc n) xs with unfold xs
... | [] = []
... | x ∷ xs′ = x ∷ take n xs′
One solution I found is to use the inspect idiom. Apparently with abstractions in agda don't propagate equalities. The inspect idiom makes the equality obvious.
data Uncons (A : Set) : Set where
Nil : Uncons A
Cons : A -> CoList A -> Uncons A
uncons : ∀ {A} -> CoList A -> Uncons A
uncons l with head l | inspect head l
uncons l | nothing | _ = Nil
uncons l | just x | [ p ] = Cons x (tail l (subst (maybe (λ _ -> ⊤) ⊥) (sym p) tt))
take : ∀ {A} -> CoList A -> (n : ℕ) -> Maybe (Vec A n)
take l zero = just []
take l (suc n) with uncons l
... | Nil = nothing
... | Cons x xs = map (λ rest → x ∷ rest) (take xs n)

agda return the even number index of the list

The code is:
filter-pos : {A : Set} → 𝕃 A → (ℕ → 𝔹) → 𝕃 A
filter-pos = {!!}
filter-pos-test : filter-pos ('a' :: 'b' :: 'c' :: 'd' :: 'e' :: 'f' :: []) is-even ≡ 'a' :: 'c' :: 'e' :: []
filter-pos-test = refl
My thought is to use nth to output nth index, use map function to make them into a list, and if it's a even number n, it will return. However, that is not working correctly.
Can someone let me know how I should go about solving this? I think it will be helpful to write a help function to solve the problem.
I'll be using the standard library.
One dumb solution is to zip a list with indices of elements, use the usual filter and then remove the indices. E.g.
'a' :: 'b' :: 'c' :: 'd' :: 'e' :: 'f' :: []
becomes
('a', 0) :: ('b', 1) :: ('c', 2) :: ('d', 3) :: ('e', 4) :: ('f', 5) :: []
filter (is-even ∘ snd) returns
('a', 0) :: ('c', 2) :: ('e', 4) :: []
and map fst results in
'a' :: 'c' :: 'e' :: []
A more natural solution is to traverse a list and increment a counter on each recursive call:
filter-pos : {A : Set} → List A → (ℕ → Bool) → List A
filter-pos {A} xs p = go 0 xs where
go : ℕ -> List A -> List A
go i [] = []
go i (x ∷ xs) = if p i then x ∷ r else r where
r = go (suc i) xs
Here i is the index of an element. However now whenever you need to prove something about filter-pos, you'll need to prove a lemma about go first, because it's go does the actual job, while filter-pos is just a wrapper around it. An idiomatic solution looks like this:
filter-pos : {A : Set} → List A → (ℕ → Bool) → List A
filter-pos [] p = []
filter-pos (x ∷ xs) p = if p 0 then x ∷ r else r where
r = filter-pos xs (p ∘ suc)
Here instead of incrementing a counter we adjust a predicate and compose it with suc. So on a first element we check whether p 0 is true, on a second element we check whether (p ∘ suc) 0 (which immediately reduces to p 1) is true, on a third element we check whether (p ∘ suc ∘ suc) 0 (which immediately reduces to p 2) is true and so on. I.e. this is the same solution as with a counter, but uses only one function.
The last version also can be tuned to work with Fin instead of ℕ
filter-pos-fin : {A : Set} → (xs : List A) → (Fin (length xs) → Bool) → List A
filter-pos-fin [] p = []
filter-pos-fin (x ∷ xs) p = if p zero then x ∷ r else r where
r = filter-pos-fin xs (p ∘ suc)

≡-Reasoning and 'with' patterns

I was proving some properties of filter and map, everything went quite good until I stumbled on this property: filter p (map f xs) ≡ map f (filter (p ∘ f) xs). Here's a part of the code that's relevant:
open import Relation.Binary.PropositionalEquality
open import Data.Bool
open import Data.List hiding (filter)
import Level
filter : ∀ {a} {A : Set a} → (A → Bool) → List A → List A
filter _ [] = []
filter p (x ∷ xs) with p x
... | true = x ∷ filter p xs
... | false = filter p xs
Now, because I love writing proofs using the ≡-Reasoning module, the first thing I tried was:
open ≡-Reasoning
open import Function
filter-map : ∀ {a b} {A : Set a} {B : Set b}
(xs : List A) (f : A → B) (p : B → Bool) →
filter p (map f xs) ≡ map f (filter (p ∘ f) xs)
filter-map [] _ _ = refl
filter-map (x ∷ xs) f p with p (f x)
... | true = begin
filter p (map f (x ∷ xs))
≡⟨ refl ⟩
f x ∷ filter p (map f xs)
-- ...
But alas, that didn't work. After trying for one hour, I finally gave up and proved it in this way:
filter-map (x ∷ xs) f p with p (f x)
... | true = cong (λ a → f x ∷ a) (filter-map xs f p)
... | false = filter-map xs f p
Still curious about why going through ≡-Reasoning didn't work, I tried something very trivial:
filter-map-def : ∀ {a b} {A : Set a} {B : Set b}
(x : A) xs (f : A → B) (p : B → Bool) → T (p (f x)) →
filter p (map f (x ∷ xs)) ≡ f x ∷ filter p (map f xs)
filter-map-def x xs f p _ with p (f x)
filter-map-def x xs f p () | false
filter-map-def x xs f p _ | true = -- not writing refl on purpose
begin
filter p (map f (x ∷ xs))
≡⟨ refl ⟩
f x ∷ filter p (map f xs)
∎
But typechecker doesn't agree with me. It would seem that the current goal remains filter p (f x ∷ map f xs) | p (f x) and even though I pattern matched on p (f x), filter just won't reduce to f x ∷ filter p (map f xs).
Is there a way to make this work with ≡-Reasoning?
Thanks!
The trouble with with-clauses is that Agda forgets the information it learned from pattern match unless you arrange beforehand for this information to be preserved.
More precisely, when Agda sees a with expression clause, it replaces all the occurences of expression in the current context and goal with a fresh variable w and then gives you that variable with updated context and goal into the with-clause, forgetting everything about its origin.
In your case, you write filter p (map f (x ∷ xs)) inside the with-block, so it goes into scope after Agda has performed the rewriting, so Agda has already forgotten the fact that p (f x) is true and does not reduce the term.
You can preserve the proof of equality by using one of the "Inspect"-patterns from the standard library, but I'm not sure how it can be useful in your case.

Resources