@@ -774,6 +774,15 @@ Proof.
774
774
by case: i.
775
775
Qed .
776
776
777
+ Lemma nth_error_firstn {A} n (l : list A) i : nth_error (firstn n l) i = if (i <? n) then nth_error l i else None.
778
+ Proof .
779
+ induction l in n, i |- *; destruct n; simpl; auto.
780
+ all: rewrite ?nth_error_nil => //.
781
+ all: try by case: Nat.ltb.
782
+ move: (IHl n (pred i)).
783
+ by case: i.
784
+ Qed .
785
+
777
786
Lemma skipn_skipn {A} n m (l : list A) : skipn n (skipn m l) = skipn (m + n) l.
778
787
Proof .
779
788
induction m in n, l |- *. auto.
@@ -813,6 +822,12 @@ Proof.
813
822
simpl. rewrite IHl; auto with arith.
814
823
Qed .
815
824
825
+ Lemma nth_error_app_full {A} (l l' : list A) (v : nat) :
826
+ nth_error (l ++ l') v = if v <? #|l| then nth_error l v else nth_error l' (v - #|l|).
827
+ Proof .
828
+ case: Nat.ltb_spec0 => ?; first [ apply nth_error_app1 | apply nth_error_app2 ]; lia.
829
+ Qed .
830
+
816
831
Lemma nth_error_app_inv X (x : X) n l1 l2 :
817
832
nth_error (l1 ++ l2) n = Some x -> (n < #|l1| /\ nth_error l1 n = Some x) \/ (n >= #|l1| /\ nth_error l2 (n - List.length l1) = Some x).
818
833
Proof .
@@ -856,6 +871,13 @@ Proof.
856
871
now rewrite Nat.sub_diag.
857
872
Qed .
858
873
874
+ Lemma nth_error_last {A l a} : l <> [] -> nth_error l (Nat.pred #|l|) = Some (@last A l a).
875
+ Proof .
876
+ induction l using rev_ind => // ?.
877
+ rewrite app_length -Nat.add_pred_r //= Nat.add_0_r nth_error_snoc //= last_last //.
878
+ Qed .
879
+
880
+
859
881
Lemma map_inj :
860
882
forall A B (f : A -> B) l l',
861
883
(forall x y, f x = f y -> x = y) ->
@@ -1468,3 +1490,154 @@ Proof.
1468
1490
{ move => [->|[n H]]; [ exists 0 | exists (S n) ];
1469
1491
rewrite ?skipn_0 ?skipn_S => //=. }
1470
1492
Qed .
1493
+
1494
+ Lemma cons_eq_iff A x xs y ys
1495
+ : x :: xs = y :: ys <-> ((x = y :> A) /\ xs = ys).
1496
+ Proof . split; intuition congruence. Qed .
1497
+
1498
+ Lemma nth_error_Some_ext_iff A (l l' : list A)
1499
+ : (#|l| = #|l'| /\ (forall n d d', nth_error l n = Some d -> nth_error l' n = Some d' -> d = d')) <-> l = l'.
1500
+ Proof .
1501
+ move: l'; induction l as [|?? IH], l' as [|? l'];
1502
+ try specialize (IH l'); cbn; try (rewrite cons_eq_iff -IH; clear IH).
1503
+ all: repeat first [ done
1504
+ | match goal with
1505
+ | [ H : _ /\ _ |- _ ] => destruct H
1506
+ | [ H : forall n d d', nth_error (_ :: _) n = Some d -> _ |- _ ]
1507
+ => pose proof (H 0); specialize (fun n => H (S n))
1508
+ | [ H : nth_error (_ :: _) ?n = _ |- _ ] => is_var n; destruct n
1509
+ end
1510
+ | exactly_once constructor
1511
+ | progress rewrite -> ?nth_error_nil in *
1512
+ | progress intros
1513
+ | progress cbn in *
1514
+ | now eauto ].
1515
+ Qed .
1516
+
1517
+ Lemma nth_error_ext_iff A (l l' : list A)
1518
+ : (forall n, nth_error l n = nth_error l' n) <-> l = l'.
1519
+ Proof .
1520
+ move: l'; induction l as [|?? IH], l' as [|? l'];
1521
+ try specialize (IH l'); cbn; try (rewrite cons_eq_iff -IH; clear IH).
1522
+ all: repeat first [ done
1523
+ | progress cbn in *
1524
+ | congruence
1525
+ | progress subst
1526
+ | match goal with
1527
+ | [ H : _ /\ _ |- _ ] => destruct H
1528
+ | [ H : forall n, nth_error (_ :: _) n = _ |- _ ]
1529
+ => pose proof (H 0); specialize (fun n => H (S n))
1530
+ | [ H : forall n, _ = nth_error (_ :: _) n |- _ ]
1531
+ => pose proof (H 0); specialize (fun n => H (S n))
1532
+ | [ H : forall n, nth_error nil n = _ |- _ ]
1533
+ => setoid_rewrite nth_error_nil in H
1534
+ | [ |- context[nth_error (_ :: _) ?n] ] => is_var n; destruct n
1535
+ end
1536
+ | exactly_once constructor
1537
+ | progress rewrite -> ?nth_error_nil in *
1538
+ | progress intros ].
1539
+ Qed .
1540
+
1541
+ Lemma In_iff_nth_error A x l : @In A x l <-> exists n, nth_error l n = Some x.
1542
+ Proof .
1543
+ split; try case; intros *; first [ apply nth_error_In | apply In_nth_error ].
1544
+ Qed .
1545
+
1546
+ Lemma List_rev_alt {A ls} : List.rev ls = @rev A ls.
1547
+ Proof . rewrite rev_alt; reflexivity. Qed .
1548
+
1549
+ Lemma nth_error_rev_full {A ls i}
1550
+ : nth_error (@rev A ls) i = if i <? #|ls| then nth_error ls (#|ls| - S i) else None.
1551
+ Proof .
1552
+ case: Nat.ltb_spec0 => ?.
1553
+ { rewrite -List_rev_alt nth_error_rev_inv //. }
1554
+ { rewrite nth_error_None rev_length; lia. }
1555
+ Qed .
1556
+
1557
+ Lemma nth_error_List_rev_full {A ls i}
1558
+ : nth_error (@List.rev A ls) i = if i <? #|ls| then nth_error ls (#|ls| - S i) else None.
1559
+ Proof .
1560
+ case: Nat.ltb_spec0 => ?.
1561
+ { rewrite nth_error_rev_inv //. }
1562
+ { rewrite nth_error_None List.rev_length; lia. }
1563
+ Qed .
1564
+
1565
+ Lemma nth_error_rev_map {A B f ls i}
1566
+ : nth_error (@rev_map A B f ls) i = if i <? #|ls| then option_map f (nth_error ls (#|ls| - S i)) else None.
1567
+ Proof .
1568
+ rewrite rev_map_spec nth_error_List_rev_full map_length nth_error_map //.
1569
+ Qed .
1570
+
1571
+ Lemma nth_error_rev_Some {A ls i v}
1572
+ : nth_error (@rev A ls) i = Some v -> nth_error ls (#|ls| - S i) = Some v.
1573
+ Proof .
1574
+ rewrite nth_error_rev_full; case: nth_error; case: Nat.ltb_spec0 => //=.
1575
+ Qed .
1576
+
1577
+ Lemma nth_error_rev_Some_inv {A ls i v}
1578
+ : nth_error ls i = Some v -> nth_error (@rev A ls) (#|ls| - S i) = Some v.
1579
+ Proof .
1580
+ rewrite nth_error_rev_full; case: Nat.ltb_spec0;
1581
+ try now case: ls => //=; rewrite ?nth_error_nil.
1582
+ intros H0 H1.
1583
+ assert (H : i < #|ls|) by now eapply nth_error_Some_length.
1584
+ now replace (#|ls| - S (#|ls| - S i)) with i by lia.
1585
+ Qed .
1586
+
1587
+ Lemma nth_error_List_rev_Some {A ls i v}
1588
+ : nth_error (@List.rev A ls) i = Some v -> nth_error ls (#|ls| - S i) = Some v.
1589
+ Proof .
1590
+ rewrite nth_error_List_rev_full; case: nth_error; case: Nat.ltb_spec0 => //=.
1591
+ Qed .
1592
+
1593
+ Lemma nth_error_List_rev_Some_inv {A ls i v}
1594
+ : nth_error ls i = Some v -> nth_error (@List.rev A ls) (#|ls| - S i) = Some v.
1595
+ Proof .
1596
+ rewrite nth_error_List_rev_full; case: Nat.ltb_spec0;
1597
+ try now case: ls => //=; rewrite ?nth_error_nil.
1598
+ intros H0 H1.
1599
+ assert (H : i < #|ls|) by now eapply nth_error_Some_length.
1600
+ now replace (#|ls| - S (#|ls| - S i)) with i by lia.
1601
+ Qed .
1602
+
1603
+ Lemma nth_error_rev_map_Some {A B f ls i v}
1604
+ : nth_error (@rev_map A B f ls) i = Some v -> { v' : _ | nth_error ls (#|ls| - S i) = Some v' /\ f v' = v }.
1605
+ Proof .
1606
+ rewrite nth_error_rev_map; case: nth_error; case: Nat.ltb_spec0 => //=.
1607
+ intros ? *; inversion 1; subst; eauto.
1608
+ Qed .
1609
+
1610
+ Lemma nth_error_rev_map_Some_inv {A B f ls i v}
1611
+ : nth_error ls i = Some v -> nth_error (@rev_map A B f ls) (#|ls| - S i) = Some (f v).
1612
+ Proof .
1613
+ rewrite nth_error_rev_map; case: Nat.ltb_spec0;
1614
+ try now case: ls => //=; rewrite ?nth_error_nil.
1615
+ intros H0 H1.
1616
+ assert (H : i < #|ls|) by now eapply nth_error_Some_length.
1617
+ replace (#|ls| - S (#|ls| - S i)) with i by lia.
1618
+ now rewrite H1.
1619
+ Qed .
1620
+
1621
+ Lemma mapi_rec_nth_error {A B f n l d k}
1622
+ : nth_error l n = Some d -> nth_error (@mapi_rec A B f l k) n = Some (f (n + k) d).
1623
+ Proof .
1624
+ move: l n k.
1625
+ elim => [|? l IH]; case => [|?] k.
1626
+ all: rewrite ?nth_error_nil => //=; try congruence.
1627
+ move => ?; rewrite IH => //.
1628
+ do 2 f_equal; lia.
1629
+ Qed .
1630
+
1631
+ Lemma mapi_nth_error {A B f n l d}
1632
+ : nth_error l n = Some d -> nth_error (@mapi A B f l) n = Some (f n d).
1633
+ Proof .
1634
+ rewrite /mapi => ?; erewrite mapi_rec_nth_error; tea; do 2 f_equal; lia.
1635
+ Qed .
1636
+
1637
+ Lemma nth_error_cons_S {A x xs n}
1638
+ : @nth_error A (x :: xs) (S n) = nth_error xs n.
1639
+ Proof . reflexivity. Qed .
1640
+
1641
+ Lemma nth_error_cons_O {A x xs}
1642
+ : @nth_error A (x :: xs) 0 = Some x.
1643
+ Proof . reflexivity. Qed .
0 commit comments