### coq

#### Coq rewriting using lambda arguments

We have a function that inserts an element into a specific index of a list. Fixpoint inject_into {A} (x : A) (l : list A) (n : nat) : option (list A) := match n, l with | 0, _ => Some (x :: l) | S k, [] => None | S k, h :: t => let kwa := inject_into x t k in match kwa with | None => None | Some l' => Some (h :: l') end end. The following property of the aforementioned function is of relevance to the problem (proof omitted, straightforward induction on l with n not being fixed): Theorem inject_correct_index : forall A x (l : list A) n, n <= length l -> exists l', inject_into x l n = Some l'. And we have a computational definition of permutations, with iota k being a list of nats [0...k]: Fixpoint permute {A} (l : list A) : list (list A) := match l with | [] => [[]] | h :: t => flat_map ( fun x => map ( fun y => match inject_into h x y with | None => [] | Some permutations => permutations end ) (iota (length t))) (permute t) end. The theorem we're trying to prove: Theorem num_permutations : forall A (l : list A) k, length l = k -> length (permute l) = factorial k. By induction on l we can (eventually) get to following goal: length (permute (a :: l)) = S (length l) * length (permute l). If we now simply cbn, the resulting goal is stated as follows: length (flat_map (fun x : list A => map (fun y : nat => match inject_into a x y with | Some permutations => permutations | None => [] end) (iota (length l))) (permute l)) = length (permute l) + length l * length (permute l) Here I would like to proceed by destruct (inject_into a x y), which is impossible considering x and y are lambda arguments. Please note that we will never get the None branch as a result of the lemma inject_correct_index. How does one proceed from this proof state? (Please do note that I am not trying to simply complete the proof of the theorem, that's completely irrelevant.)

There is a way to rewrite under binders: the setoid_rewrite tactic (see §27.3.1 of the Coq Reference manual). However, direct rewriting under lambdas is not possible without assuming an axiom as powerful as the axiom of functional extensionality (functional_extensionality). Otherwise, we could have proved: (* classical example *) Goal (fun n => n + 0) = (fun n => n). Fail setoid_rewrite <- plus_n_O. Abort. See here for more detail. Nevertheless, if you are willing to accept such axiom, then you can use the approach described by Matthieu Sozeau in this Coq Club post to rewrite under lambdas like so: Require Import Coq.Logic.FunctionalExtensionality. Require Import Coq.Setoids.Setoid. Require Import Coq.Classes.Morphisms. Generalizable All Variables. Instance pointwise_eq_ext {A B : Type} `(sb : subrelation B RB eq) : subrelation (pointwise_relation A RB) eq. Proof. intros f g Hfg. apply functional_extensionality. intro x; apply sb, (Hfg x). Qed. Goal (fun n => n + 0) = (fun n => n). setoid_rewrite <- plus_n_O. reflexivity. Qed.

### Related Links

apply tactic cannot find an instance for a variable

Introducing new hypothesis in the premises

Adding complete disjunctive assumption in Coq

Can´t destruct exists in hypothesis

Re-writing without using symmetry tactic

Inversion on large types with impredicative-set enabled

How does the discriminate tactic work?

Smart modification of Coq environment

Lexicographical comparison of tuples of nats

Multiple Where-clauses for Reserved Notation in Coq?

Writing well-founded programs in Coq using Fix or Program Fixpoint

Pigeonhole proof without decidable equality or excluded middle

Can I use a notation for an Inductive type to define that type in Coq?

Applying apply tactic to premises instead of the goal

Coq Real numbers -lexing and parsing 3.14

Supplying section arguments for examples