@@ -369,6 +369,38 @@ Proof.
369369 cbn in Hlen. firstorder.
370370Qed .
371371
372+ Fixpoint update_nth {A : Type } n (l : list A) (a : A) :=
373+ match l with
374+ | nil => nil
375+ | cons x l' => match n with
376+ | 0 => cons a l'
377+ | S n' => cons x (update_nth n' l' a)
378+ end
379+ end .
380+
381+ Lemma update_decr ind n l : ind < length l -> n = List.nth ind l 0 -> n > 0 -> List.list_sum (update_nth ind l (pred n)) < List.list_sum l.
382+ Proof .
383+ intros Hlen Hind Hgt0.
384+ induction l as [| x l IH] in ind, Hlen, Hind, Hgt0 |- *.
385+ - cbn in Hlen. lia.
386+ - cbn in Hlen.
387+ destruct ind as [| ind].
388+ + cbn in *; subst.
389+ lia.
390+ + cbn in *. specialize (IH ind).
391+ apply PeanoNat.lt_S_n in Hlen.
392+ firstorder. unfold List.list_sum in H. lia.
393+ Qed .
394+
395+ Lemma update_length {A : Type} (l: list A) n v : length (update_nth n l v) = length l.
396+ Proof .
397+ induction l as [| x l IH] in n |- *.
398+ - destruct n; reflexivity.
399+ - destruct n.
400+ + cbn. reflexivity.
401+ + cbn. congruence.
402+ Qed .
403+
372404Lemma max_steps_list_decr t1 t2 l l' outer :
373405 t1 ~> t2 ->
374406 length l' = length (outer ++ t1 :: l) ->
@@ -382,40 +414,80 @@ Lemma max_steps_list_decr t1 t2 l l' outer :
382414 end -> length l <= n) (List.combine (outer ++ t1 :: l) l') ->
383415 exists l'',
384416 List.list_sum l'' < List.list_sum l'
385- /\ length l'' = length (outer ++ t1 :: l)
417+ /\ length l'' = length (outer ++ t2 :: l)
386418 /\ List.Forall
387419 (fun p : prod term nat =>
388420 let (t0, n) := p in
389421 forall l0 : list term,
390422 match l0 with
391423 | []%list => True
392424 | (t2 :: _)%list => t0 ~> t2 /\ reduction_sequence l0
393- end -> length l0 <= n) (List.combine (outer ++ t1 :: l) l'').
425+ end -> length l0 <= n) (List.combine (outer ++ t2 :: l) l'').
394426Proof .
395427 intros Hstep Hlen Hl'.
396- assert (List.In t1 (outer ++ t1 :: l)) as Hin.
397- - auto with datatypes.
398- - apply List.In_nth with (d := Var 0) in Hin as (ind & Hind & Hin).
399- rewrite (List.Forall_forall) in Hl'.
400- pose (List.nth ind l' 0) as n.
401- assert (List.In (t1, n) (List.combine (outer ++ t1 :: l) l')) as H.
402- { assert ((t1, n) = List.nth ind (List.combine (outer ++ t1 :: l) l') (Var 0, 0)) as Hnth.
403- - rewrite <- Hin.
404- rewrite List.combine_nth.
405- + repeat f_equal.
406- congruence.
407- + rewrite Hlen. congruence.
408- - rewrite Hnth. apply List.nth_In.
409- rewrite List.combine_length.
410- lia.
411- }
412- apply Hl' in H.
413- pose proof (max_steps_decr t1 n H t2 Hstep) as Hdecr.
414- pose proof (max_steps_nonzero t1 t2 n Hstep H) as Hnz.
415-
416- (*ideally, we would like to have some kind of list update function here with the desired properties. We don't.*)
417- (*induction on outer won't work: we don't get from List.nth ind (t1 :: l) _ = t1 that ind = 0. *)
418- Admitted .
428+ pose (length outer) as ind.
429+ assert (ind < length (outer ++ t1 :: l)) as Hind.
430+ {
431+ clear.
432+ induction outer; cbn in *; lia.
433+ }
434+ assert (List.nth ind (outer ++ t1 :: l) (Var 0) = t1) as Hin.
435+ {
436+ clear.
437+ induction outer; cbn in *.
438+ - reflexivity.
439+ - assumption.
440+ }
441+ rewrite (List.Forall_forall) in Hl'.
442+ pose (List.nth ind l' 0) as n.
443+ assert (List.In (t1, n) (List.combine (outer ++ t1 :: l) l')) as H.
444+ { assert ((t1, n) = List.nth ind (List.combine (outer ++ t1 :: l) l') (Var 0, 0)) as Hnth.
445+ - rewrite <- Hin.
446+ rewrite List.combine_nth.
447+ + repeat f_equal.
448+ congruence.
449+ + rewrite Hlen. congruence.
450+ - rewrite Hnth. apply List.nth_In.
451+ rewrite List.combine_length.
452+ lia.
453+ }
454+ apply Hl' in H.
455+ pose proof (max_steps_decr t1 n H t2 Hstep) as Hdecr.
456+ pose proof (max_steps_nonzero t1 t2 n Hstep H) as Hnz.
457+
458+ exists (update_nth ind l' (pred n)).
459+ split. 1: {
460+ apply update_decr.
461+ - lia.
462+ - reflexivity.
463+ - assumption.
464+ }
465+ split. 1: {
466+ rewrite update_length.
467+ rewrite Hlen.
468+ clear.
469+ induction outer; cbn.
470+ - reflexivity.
471+ - congruence.
472+ }
473+ rewrite <- List.Forall_forall in Hl'.
474+ clear - Hdecr Hl' Hlen.
475+ unfold ind in *.
476+
477+ induction outer in l', Hl', n, Hlen, Hdecr |- *.
478+ - cbn in *. destruct l'.
479+ + constructor.
480+ + constructor.
481+ * exact Hdecr.
482+ * inversion Hl'; subst. assumption.
483+ - destruct l'; cbn in *.
484+ + congruence.
485+ + inversion Hl'.
486+ constructor.
487+ * assumption.
488+ * apply IHouter; try assumption.
489+ now inversion Hlen.
490+ Qed .
419491
420492(* Lemma 3.2.1 statement (3) for the base case, where the entire term is of some atomic type.
421493 Formalizing this proof is difficult:
@@ -530,17 +602,17 @@ Proof.
530602 rewrite (nested_app_app).
531603 destruct Hl' as [Hl'1 Hl'2].
532604 pose proof (max_steps_list_decr t1 t' l l' outer Hstep Hl'1 Hl'2) as (l'' & Hdecr & Hl'').
605+ constructor.
533606 eapply IH.
534- 2: exact Hsn.
535- 2: exact Hsnu.
536- 2, 3: eassumption.
537- 3: reflexivity.
538- 3: {
539- clear - Hstep.
540- induction outer; now constructor.
541- }
542- 2: exact Hl''.
543- lia.
607+ 3: exact Hsnu.
608+ 3: exact Hnt.
609+ 3: exact Hnu.
610+ 4: reflexivity.
611+ 3: exact Hl''.
612+ 1: lia.
613+ eapply SN_inverted. 1: exact Hsn.
614+ clear - Hstep.
615+ induction outer; now constructor.
544616 - destruct l; cbn in Heqtrm; congruence.
545617Qed .
546618
@@ -731,4 +803,4 @@ Proof.
731803 intros.
732804 apply reducible_var with Γ.
733805 now apply Typing_Var.
734- Qed
806+ Qed .
0 commit comments