(* The algorithm is defined as follows:
   - if the heap is h1 :+ h2, then recurse over h1 and h2 and concatenate the
     results.
   - if the heap is x :-> v, then return [x]
   - otherwise, return []
*)

(* Structure to control the flow of the algorithm *)
Structure tagged_heap := Tag {untag : heap}.(* The algorithm is defined as follows:
   - if the heap is h1 :+ h2, then recurse over h1 and h2 and concatenate the
     results.
   - if the heap is x :-> v, then return [x]
   - otherwise, return []
*)

(* Structure to control the flow of the algorithm *)
Structure tagged_heap := Tag {untag : heap}.(* The algorithm is defined as follows:
   - if the heap is h1 :+ h2, then recurse over h1 and h2 and concatenate the
     results.
   - if the heap is x :-> v, then return [x]
   - otherwise, return []
*)

(* Structure to control the flow of the algorithm *)
Structure tagged_heap := Tag {untag : heap}.Definition default_tag := Tag.Definition ptr_tag := default_tag.Canonical Structure union_tag h := ptr_tag h.(* Main structure *)
Structure form s := Form {heap_of : tagged_heap; _ : axiom heap_of s}.(* Main structure *)
Structure form s := Form {heap_of : tagged_heap; _ : axiom heap_of s}.(* Main structure *)
Structure form s := Form {heap_of : tagged_heap; _ : axiom heap_of s}.Canonical Structure union_form s1 s2 h1 h2 :=
  Form (@union_pf s1 s2 h1 h2).Canonical Structure ptr_form A x (v : A) :=
  Form (@ptr_pf A x v).Canonical Structure default_form h := Form (@default_pf h).(* The algorithm is defined as follow:
   - test if the list is (x :: s) for x being the element we are looking for
   - if the list is (y :: s), then recurse using s
*)

(* Stucture for controlling the flow of the algorithm *)
Structure tagged_seq := Tag {untag : seq ptr}.(* The algorithm is defined as follow:
   - test if the list is (x :: s) for x being the element we are looking for
   - if the list is (y :: s), then recurse using s
*)

(* Stucture for controlling the flow of the algorithm *)
Structure tagged_seq := Tag {untag : seq ptr}.(* The algorithm is defined as follow:
   - test if the list is (x :: s) for x being the element we are looking for
   - if the list is (y :: s), then recurse using s
*)

(* Stucture for controlling the flow of the algorithm *)
Structure tagged_seq := Tag {untag : seq ptr}.Definition recurse_tag := Tag.Canonical Structure found_tag s := recurse_tag s.(* Main structure *)
Structure form x := Form {seq_of : tagged_seq; _ : axiom x seq_of}.(* Main structure *)
Structure form x := Form {seq_of : tagged_seq; _ : axiom x seq_of}.(* Main structure *)
Structure form x := Form {seq_of : tagged_seq; _ : axiom x seq_of}.

Lemma found_pf x s : axiom x (found_tag (x :: s)).