I have the following definition for terms :
Inductive term : Type :=
| Var : variable -> term
| Func : function_symbol -> list term -> term.
and a function pos_list
taking a list of terms and returning a list of "positions" for each subterms. For instance for [Var "e"; Func "f" [Var "x"; Func "i" [Var "x"]]]
I should get [[1]; [2]; [2; 1]; [2; 2]; [2; 2; 1]]
where each element represents a position in the tree-hierarchy of subterms.
Definition pos_list (args:list term) : list position :=
let fix pos_list_aux ts is head :=
let enumeration := enumerate ts in
let fix post_enumeration ts is head :=
match is with
| [] => []
| y::ys =>
let new_head := (head++y) in
match ts with
| [] => []
| (Var _)::xs => [new_head] ++ (post_enumeration xs ys head)
| (Func _ args')::xs =>
[new_head] ++
(pos_list_aux args' [] new_head) ++
(post_enumeration xs ys head)
end
end
in post_enumeration ts enumeration head
in pos_list_aux args [] [].
With the above code I get the error
Error: Cannot guess decreasing argument of
fix
on the first let fix
construction but it seems to me that the call to (pos_list_aux args' [] new_head)
(which is causing problems) takes as argument args'
which is a subterm of (Func _ args')
which is itself a subterm of ts
.
What is wrong ?
term
is a nested inductive type (because oflist term
in theFunc
constructor) and it frequently requires some additional work to explain to Coq that your function is total. This chapter of CPDT explains how to deal with this kind of situation (see "Nested inductive types" section):Here is my attempt at solving your problem. First of all, let's add some imports and definitions so everything compiles:
We begin by implementing a function that does the job for a single
term
. Notice that we define a nested functionpos_list_many_aux
which is almost what you wanted in the first place:Now, we will need an auxiliary function
mapi
(named borrowed from OCaml's stdlib). It's likemap
, but the mapping function also receives the index of the current list element.And now everything is ready to define the
pos_list
function:Let's run your test: