Why does 'neutral' not normalize to '[]' in the List monoid? - typeclass

The following Idris definition typechecks with Idris 1.3.0:
foo : (xs : List Nat) -> xs = ([] <+> xs)
foo xs = Refl
however, this doesn't:
foo : (xs : List Nat) -> xs = (neutral <+> xs)
foo xs = Refl
giving the following type error:
When checking right hand side of foo with expected type
xs = neutral <+> xs
Type mismatch between
neutral ++ xs = neutral ++ xs (Type of Refl)
and
xs = neutral ++ xs (Expected type)
Specifically:
Type mismatch between
neutral ++ xs
and
xs
Why does neutral <+> xs not normalize to xs here?

neutral will be interpreted as a implicit argument because it's lower case and appears in a type declaration. But you can just specify the module. :doc neutral gives me Prelude.Algebra.neutral:
foo : (xs : List Nat) -> xs = (Algebra.neutral <+> xs)
foo xs = Refl

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 ]

How to do a rewrite in a premise?

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.

Cryptic error: `.A !=< .A₁ of type Set` in simple function

The following Agda function should lookup a list, looping back on index overflows:
module Test where
open import Prelude.Nat
open import Prelude.List
roundIndex : {A : Set} -> Nat -> A -> List A -> A
roundIndex n x xs = go n xs where
go : {A : Set} -> Nat -> List A -> A
go (suc n) (x ∷ xs) = go n xs
go (suc n) [] = go n xs
go zero (x ∷ xs) = x
go zero [] = x
But won't compile with the following cryptic error:
/Users/v/vic/dev/agda/Test.agda:10,25-32
.A !=< .A₁ of type Set
when checking that the expression go n xs has type .A₁
It seems like Agda isn't properly passing the implicit A to go, but passing it explicitly didn't solve the problem. What is this error? Also, that is !=<?
The error is that go works for any A, but you try to return outer x and xs with outer A types. The go-bound A and roundIndex-bound A types are different, hence the error. In general, bound type variables are only equal to themselves during conversion checking. It's not Agda-specific, as you could reproduce the same error in Haskell as well.
The solution is to remove the inner type quantification:
roundIndex : {A : Set} -> Nat -> A -> List A -> A
roundIndex {A} n x xs = go n xs where
go : Nat -> List A -> A
go (suc n) (x ∷ xs) = go n xs
go (suc n) [] = go n xs
go zero (x ∷ xs) = x
go zero [] = x
Now there's only one shared A around.

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)

Problems on data type indices that uses list concatenation

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.

Resources