Consider the following type definition of a sized list:
Inductive listn: nat -> Type -> Type :=
| nil: forall {A: Set}, listn 0 A
| cons: forall {n: nat} {A: Set}, A -> listn n A -> listn (S n) A.
This is essentially the Vect type in Idris.
I am trying to define the init function for listn, which removes the last element.
My attempted implementation was virtually identical to the definition of init in Idris. Here it is in Idris:
init : Vect (S len) elem -> Vect len elem
init (x::[]) = []
init (x::y::ys) = x :: init (y::ys)
Transcribed into Coq:
Fixpoint init {n: nat} {A: Set} (l: listn (S n) A): listn n A :=
match l with
| cons x nil => nil
| cons x (cons y ys) => cons x (init (cons y ys))
end.
…but this fails with:
The term "nil" has type "listn 0 ?A"
while it is expected to have type "listn ?n ?S@{a0:=S}"
(cannot unify "?n" and "0").
I take it that Coq isn't able to see that the case necessarily implies that n is zero. This is a problem I keep running into – Coq isn't able to see the relationship between n and the list itself.
Hence my questions:
- How can
initbe implemented in Coq? - Why does the Idris definition work in Idris but not in Coq? What is Idris doing behind the scenes that Coq isn't?