Problems on data type indices that uses list concatenation - agda

I'm having a nasty problem with a formalisation of a theorem that uses a data type that have some constructors whose indices have list concatenation. When I try to use emacs mode to case split, Agda returns the following error message:
I'm not sure if there should be a case for the constructor
o-success, because I get stuck when trying to solve the following
unification problems (inferred index ≟ expected index):
e₁ o e'' , x₁ ++ x'' ++ y₁ ≟ e o e' , x ++ x' ++ y
suc (n₂ + n'') , x₁ ++ x'' ≟ m' , p''
when checking that the expression ? has type
suc (.n₁ + .n') == .m' × .x ++ .x' == p'
Since the code is has more than a small number of lines, I put it on the following gist:
https://gist.github.com/rodrigogribeiro/976b3d5cc82c970314c2
Any tip is appreciated.
Best,

There was a similar question.
However you want to unify xs1 ++ xs2 ++ xs3 with ys1 ++ ys2 ++ ys3, but _++_ is not a constructor — it's a function, and it's not injective. Consider this simplified example:
data Bar {A : Set} : List A -> Set where
bar : ∀ xs {ys} -> Bar (xs ++ ys)
ex : ∀ {A} {zs : List A} -> Bar zs -> Bar zs -> List A
ex (bar xs) b = {!!}
b is of type Bar (xs ++ .ys), but b is not necessarily equal to bar .xs, so you can't pattern-match like this. Here are two Bars, which have equal types but different values:
ok : ∃₂ λ (b1 b2 : Bar (tt ∷ [])) -> b1 ≢ b2
ok = bar [] , bar (tt ∷ []) , λ ()
This is because xs1 ++ xs2 ≡ ys1 ++ ys2 doesn't imply xs1 ≡ ys1 × xs2 ≡ ys2 in general.
But it's possible to generalize an index. You can use the technique described by Vitus at the link above, or you can use this simple combinator, which forgets the index:
generalize : ∀ {α β} {A : Set α} (B : A -> Set β) {x : A} -> B x -> ∃ B
generalize B y = , y
E.g.
ex : ∀ {A} {zs : List A} -> Bar zs -> Bar zs -> List A
ex {A} (bar xs) b with generalize Bar b
... | ._ , bar ys = xs ++ ys
After all, are you sure your lemma is true?
UPDATE
Some remarks first.
Your empty case states
empty : forall x -> G :: (emp , x) => (1 , x)
that the empty parser parses the whole string. It should be
empty : forall x -> G :: (emp , x) => (1 , [])
as in the paper.
Your definition of o-fail1 contains this part:
(n , fail ∷ o)
but fail fails everything, so it should be (n , fail ∷ []). With this representation you would probably need decidable equality on A to finish the lemma, and proofs would be dirty. Clean and idiomatic way to represent something, that can fail, is to wrap it in the Maybe monad, so here is my definition of _::_=>_:
data _::_=>_ {n} (G : Con n) : Foo n × List A -> Nat × Maybe (List A) -> Set where
empty : ∀ {x} -> G :: emp , x => 1 , just []
sym-success : ∀ {a x} -> G :: sym a , (a ∷ x) => 1 , just (a ∷ [])
sym-failure : ∀ {a b x} -> ¬ (a == b) -> G :: sym a , b ∷ x => 1 , nothing
var : ∀ {x m o} {v : Fin (suc n)}
-> G :: lookup v G , x => m , o -> G :: var v , x => suc m , o
o-success : ∀ {e e' x x' y n n'}
-> G :: e , x ++ x' ++ y => n , just x
-> G :: e' , x' ++ y => n' , just x'
-> G :: e o e' , x ++ x' ++ y => suc (n + n') , just (x ++ x')
o-fail1 : ∀ {e e' x x' y n}
-> G :: e , x ++ x' ++ y => n , nothing
-> G :: e o e' , x ++ x' ++ y => suc n , nothing
o-fail2 : ∀ {e e' x x' y n n'}
-> G :: e , x ++ x' ++ y => n , just x
-> G :: e' , x' ++ y => n' , nothing
-> G :: e o e' , x ++ x' ++ y => suc (n + n') , nothing
Here is the lemma:
postulate
cut : ∀ {α} {A : Set α} -> ∀ xs {ys zs : List A} -> xs ++ ys == xs ++ zs -> ys == zs
mutual
aux : ∀ {n} {G : Con n} {e e' z x x' y n n' m' p'}
-> z == x ++ x' ++ y
-> G :: e , z => n , just x
-> G :: e' , x' ++ y => n' , just x'
-> G :: e o e' , z => m' , p'
-> suc (n + n') == m' × just (x ++ x') == p'
aux {x = x} {x'} {n = n} {n'} r pr1 pr2 (o-success {x = x''} pr3 pr4) with x | n | lemma pr1 pr3
... | ._ | ._ | refl , refl rewrite cut x'' r with x' | n' | lemma pr2 pr4
... | ._ | ._ | refl , refl = refl , refl
aux ...
lemma : ∀ {n m m'} {G : Con n} {f x p p'}
-> G :: f , x => m , p -> G :: f , x => m' , p' -> m == m' × p == p'
lemma (o-success pr1 pr2) pr3 = aux refl pr1 pr2 pr3
lemma ...
The proof proceeds as follows:
We generalize the type of lemma's pr3 in an auxiliary function as in the Vitus' answer. Now it's possible to pattern-match on pr3.
We prove, that the first parser in lemma's pr3 (called also pr3 in the aux) produces the same output as pr1.
After some rewriting, we prove that the second parser in lemma's pr3 (called pr4 in the aux) produces the same output as pr2.
And since pr1 and pr3 produce the same output, and pr2 and pr4 produce the same output, o-success pr1 pr2 and o-success pr3 pr4 produce the same output, so we put refl , refl.
The code. I didn't prove the o-fail1 and o-fail2 cases, but they should be similar.
UPDATE
Amount of boilerplate can be reduced by
Fixing the definitions of the fail cases, which contain redundant information.
Returning Maybe (List A) instead of Nat × Maybe (List A). You can compute this Nat recursively, if needed.
Using the inspect idiom instead of auxiliary functions.
I don't think there is a simpler solution. The code.

Related

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)

Agda type-safe cast / coercion

I found handy a function:
coerce : ∀ {ℓ} {A B : Set ℓ} → A ≡ B → A → B
coerce refl x = x
when defining functions with indexed types. In situations where indexes are not definitionally equal i,e, one have to use lemma, to show the types match.
zipVec : ∀ {a b n m } {A : Set a} {B : Set b} → Vec A n → Vec B m → Vec (A × B) (n ⊓ m)
zipVec [] _ = []
zipVec {n = n} _ [] = coerce (cong (Vec _) (0≡n⊓0 n)) []
zipVec (x ∷ xs) (y ∷ ys) = (x , y) ∷ zipVec xs ys
Note, yet this example is easy to rewrite so one don't need to coerce:
zipVec : ∀ {a b n m } {A : Set a} {B : Set b} → Vec A n → Vec B m → Vec (A × B) (n ⊓ m)
zipVec [] _ = []
zipVec (_ ∷ _) [] = []
zipVec (x ∷ xs) (y ∷ ys) = (x , y) ∷ zipVec xs ys
Sometimes pattern matching doesn't help though.
The question: But I wonder, whether something like that functions is already in agda-stdlib? And is there something like hoogle for Agda, or something like SearchAbout?
I don't think there is exactly your coerce function. However, it's a special case of a more general function - subst (the substitutive property of equality) from Relation.Binary.PropositionalEquality:
subst : ∀ {a p} {A : Set a} (P : A → Set p) {x y : A}
→ x ≡ y → P x → P y
subst P refl p = p
If you choose P = id (from Data.Function, or just write λ x → x), you get:
coerce : ∀ {ℓ} {A B : Set ℓ} → A ≡ B → A → B
coerce = subst id
By the way, the most likely reason you won't find this function predefined, is that Agda deals with coerces like that through rewrite:
postulate
n⊓0≡0 : ∀ n → n ⊓ 0 ≡ 0
zipVec : ∀ {a b n m} {A : Set a} {B : Set b}
→ Vec A n → Vec B m → Vec (A × B) (n ⊓ m)
zipVec [] _ = []
zipVec {n = n} _ [] rewrite n⊓0≡0 n = []
zipVec (x ∷ xs) (y ∷ ys) = (x , y) ∷ zipVec xs ys
This is a syntactic sugar for the more complicated:
zipVec {n = n} _ [] with n ⊓ 0 | n⊓0≡0 n
... | ._ | refl = []
If you are familiar with how with works, try to figure out how rewrite works; it's quite enlightening.

Termination check on list merge

Agda 2.3.2.1 can't see that the following function terminates:
open import Data.Nat
open import Data.List
open import Relation.Nullary
merge : List ℕ → List ℕ → List ℕ
merge (x ∷ xs) (y ∷ ys) with x ≤? y
... | yes p = x ∷ merge xs (y ∷ ys)
... | _ = y ∷ merge (x ∷ xs) ys
merge xs ys = xs ++ ys
Agda wiki says that it's OK for the termination checker if the arguments on recursive calls decrease lexicographically. Based on that it seems that this function should also pass. So what am I missing here? Also, is it maybe OK in previous versions of Agda? I've seen similar code on the Internet and no one mentioned termination issues there.
I cannot give you the reason why exactly this happens, but I can show you how to cure the symptoms. Before I start: This is a known problem with the termination checker. If you are well-versed in Haskell, you could take a look at the source.
One possible solution is to split the function into two: first one for the case where the first argument gets smaller and second for the second one:
mutual
merge : List ℕ → List ℕ → List ℕ
merge (x ∷ xs) (y ∷ ys) with x ≤? y
... | yes _ = x ∷ merge xs (y ∷ ys)
... | no _ = y ∷ merge′ x xs ys
merge xs ys = xs ++ ys
merge′ : ℕ → List ℕ → List ℕ → List ℕ
merge′ x xs (y ∷ ys) with x ≤? y
... | yes _ = x ∷ merge xs (y ∷ ys)
... | no _ = y ∷ merge′ x xs ys
merge′ x xs [] = x ∷ xs
So, the first function chops down xs and once we have to chop down ys, we switch to the second function and vice versa.
Another (perhaps surprising) option, which is also mentioned in the issue report, is to introduce the result of recursion via with:
merge : List ℕ → List ℕ → List ℕ
merge (x ∷ xs) (y ∷ ys) with x ≤? y | merge xs (y ∷ ys) | merge (x ∷ xs) ys
... | yes _ | r | _ = x ∷ r
... | no _ | _ | r = y ∷ r
merge xs ys = xs ++ ys
And lastly, we can perform the recursion on Vectors and then convert back to List:
open import Data.Vec as V
using (Vec; []; _∷_)
merge : List ℕ → List ℕ → List ℕ
merge xs ys = V.toList (go (V.fromList xs) (V.fromList ys))
where
go : ∀ {n m} → Vec ℕ n → Vec ℕ m → Vec ℕ (n + m)
go {suc n} {suc m} (x ∷ xs) (y ∷ ys) with x ≤? y
... | yes _ = x ∷ go xs (y ∷ ys)
... | no _ rewrite lem n m = y ∷ go (x ∷ xs) ys
go xs ys = xs V.++ ys
However, here we need a simple lemma:
open import Relation.Binary.PropositionalEquality
lem : ∀ n m → n + suc m ≡ suc (n + m)
lem zero m = refl
lem (suc n) m rewrite lem n m = refl
We could also have go return List directly and avoid the lemma altogether:
merge : List ℕ → List ℕ → List ℕ
merge xs ys = go (V.fromList xs) (V.fromList ys)
where
go : ∀ {n m} → Vec ℕ n → Vec ℕ m → List ℕ
go (x ∷ xs) (y ∷ ys) with x ≤? y
... | yes _ = x ∷ go xs (y ∷ ys)
... | no _ = y ∷ go (x ∷ xs) ys
go xs ys = V.toList xs ++ V.toList ys
The first trick (i.e. split the function into few mutually recursive ones) is actually quite good to remember. Since the termination checker doesn't look inside the definitions of other functions you use, it rejects a great deal of perfectly fine programs, consider:
data Rose {a} (A : Set a) : Set a where
[] : Rose A
node : A → List (Rose A) → Rose A
And now, we'd like to implement mapRose:
mapRose : ∀ {a b} {A : Set a} {B : Set b} →
(A → B) → Rose A → Rose B
mapRose f [] = []
mapRose f (node t ts) = node (f t) (map (mapRose f) ts)
The termination checker, however, doesn't look inside the map to see if it doesn't do anything funky with the elements and just rejects this definition. We must inline the definition of map and write a pair of mutually recursive functions:
mutual
mapRose : ∀ {a b} {A : Set a} {B : Set b} →
(A → B) → Rose A → Rose B
mapRose f [] = []
mapRose f (node t ts) = node (f t) (mapRose′ f ts)
mapRose′ : ∀ {a b} {A : Set a} {B : Set b} →
(A → B) → List (Rose A) → List (Rose B)
mapRose′ f [] = []
mapRose′ f (t ∷ ts) = mapRose f t ∷ mapRose′ f ts
Usually, you can hide most of the mess in a where declaration:
mapRose : ∀ {a b} {A : Set a} {B : Set b} →
(A → B) → Rose A → Rose B
mapRose {A = A} {B = B} f = go
where
go : Rose A → Rose B
go-list : List (Rose A) → List (Rose B)
go [] = []
go (node t ts) = node (f t) (go-list ts)
go-list [] = []
go-list (t ∷ ts) = go t ∷ go-list ts
Note: Declaring signatures of both functions before they are defined can be used instead of mutual in newer versions of Agda.
Update: The development version of Agda got an update to the termination checker, I'll let the commit message and release notes speak for themselves:
A revision of call graph completion that can deal with arbitrary termination depth.
This algorithm has been sitting around in MiniAgda for some time,
waiting for its great day. It is now here!
Option --termination-depth can now be retired.
And from the release notes:
Termination checking of functions defined by 'with' has been improved.
Cases which previously required --termination-depth (now obsolete!)
to pass the termination checker (due to use of 'with') no longer
need the flag. For example
merge : List A → List A → List A
merge [] ys = ys
merge xs [] = xs
merge (x ∷ xs) (y ∷ ys) with x ≤ y
merge (x ∷ xs) (y ∷ ys) | false = y ∷ merge (x ∷ xs) ys
merge (x ∷ xs) (y ∷ ys) | true = x ∷ merge xs (y ∷ ys)
This failed to termination check previously, since the 'with'
expands to an auxiliary function merge-aux:
merge-aux x y xs ys false = y ∷ merge (x ∷ xs) ys
merge-aux x y xs ys true = x ∷ merge xs (y ∷ ys)
This function makes a call to merge in which the size of one of the
arguments is increasing. To make this pass the termination checker
now inlines the definition of merge-aux before checking, thus
effectively termination checking the original source program.
As a result of this transformation doing 'with' on a variable no
longer preserves termination. For instance, this does not
termination check:
bad : Nat → Nat
bad n with n
... | zero = zero
... | suc m = bad m
And indeed, your original function now passes the termination check!

Implicit arguments and applying a function to the tail-part of fixed-size-vectors

I wrote an Agda-function applyPrefix to apply a fixed-size-vector-function to the initial part of a longer vector where the vector-sizes m, n and k may stay implicit. Here's the definition together with a helper-function split:
split : ∀ {A m n} → Vec A (n + m) → (Vec A n) × (Vec A m)
split {_} {_} {zero} xs = ( [] , xs )
split {_} {_} {suc _} (x ∷ xs) with split xs
... | ( ys , zs ) = ( (x ∷ ys) , zs )
applyPrefix : ∀ {A n m k} → (Vec A n → Vec A m) → Vec A (n + k) → Vec A (m + k)
applyPrefix f xs with split xs
... | ( ys , zs ) = f ys ++ zs
I need a symmetric function applyPostfix which applies a fixed-size-vector-function to the tail-part of a longer vector.
applyPostfix ∀ {A n m k} → (Vec A n → Vec A m) → Vec A (k + n) → Vec A (k + m)
applyPostfix {k = k} f xs with split {_} {_} {k} xs
... | ( ys , zs ) = ys ++ (f zs)
As the definition of applyPrefix already shows, the k-Argument cannot stay implicit when applyPostfix is used. For example:
change2 : {A : Set} → Vec A 2 → Vec A 2
change2 ( x ∷ y ∷ [] ) = (y ∷ x ∷ [] )
changeNpre : {A : Set}{n : ℕ} → Vec A (2 + n) → Vec A (2 + n)
changeNpre = applyPrefix change2
changeNpost : {A : Set}{n : ℕ} → Vec A (n + 2) → Vec A (n + 2)
changeNpost = applyPost change2 -- does not work; n has to be provided
Does anyone know a technique, how to implement applyPostfix so that the k-argument may stay implicit when using applyPostfix?
What I did is proofing / programming:
lem-plus-comm : (n m : ℕ) → (n + m) ≡ (m + n)
and use that lemma when defining applyPostfix:
postfixApp2 : ∀ {A}{n m k : ℕ} → (Vec A n → Vec A m) → Vec A (k + n) → Vec A (k + m)
postfixApp2 {A} {n} {m} {k} f xs rewrite lem-plus-comm n k | lem-plus-comm k n | lem-plus-comm k m | lem-plus-comm m k = reverse (drop {n = n} (reverse xs)) ++ f (reverse (take {n = n} (reverse xs)))
Unfortunately, this didnt help, since I use the k-Parameter for calling the lemma :-(
Any better ideas how to avoid k to be explicit? Maybe I should use a snoc-View on Vectors?
What you can do is to give postfixApp2 the same type as applyPrefix.
The source of the problem is that a natural number n can be unified with p + q only if p is known. This is because + is defined via induction on the first argument.
So this one works (I'm using the standard-library version of commutativity on +):
+-comm = comm
where
open IsCommutativeSemiring isCommutativeSemiring
open IsCommutativeMonoid +-isCommutativeMonoid
postfixApp2 : {A : Set} {n m k : ℕ}
→ (Vec A n → Vec A m)
→ Vec A (n + k) → Vec A (m + k)
postfixApp2 {A} {n} {m} {k} f xs rewrite +-comm n k | +-comm m k =
applyPostfix {k = k} f xs
Yes, I'm reusing the original applyPostfix here and just give it a different type by rewriting twice.
And testing:
changeNpost : {A : Set} {n : ℕ} → Vec A (2 + n) → Vec A (2 + n)
changeNpost = postfixApp2 change2
test : changeNpost (1 ∷ 2 ∷ 3 ∷ 4 ∷ []) ≡ 1 ∷ 2 ∷ 4 ∷ 3 ∷ []
test = refl

≡-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