GhostTT.Util

From Coq Require Import Utf8 List Bool.
From Equations Require Import Equations.

Import ListNotations.

Set Default Goal Selector "!".

Notation "'∑' x .. y , p" := (sigT (λ x, .. (sigT (λ y, p%type)) ..))
  (at level 200, x binder, right associativity,
   format "'[' '∑' '/ ' x .. y , '/ ' p ']'")
  : type_scope.

Ltac forall_iff_impl T :=
  lazymatch eval cbn beta in T with
  | x : ?A, @?T' x
    let y := fresh x in
    refine ( y, _) ;
    forall_iff_impl (@T' x)
  | ?P ?Qexact (P Q)
  | _fail "not a quantified ↔"
  end.

Ltac wlog_iff_using tac :=
  lazymatch goal with
  | |- ?G
    let G' := fresh in
    unshelve refine (let G' : Prop := _ in _) ; [ forall_iff_impl G |] ;
    let h := fresh in
    assert (h : G') ; [
      subst G'
    | subst G' ; intros ; split ; eauto ; apply h ; clear h ; tac
    ]
  end.

Ltac wlog_iff :=
  wlog_iff_using firstorder.

Create HintDb shelvedb.

Hint Extern 10000 ⇒ shelve : shelvedb.

Ltac destruct_if e :=
  lazymatch goal with
  | |- context [ if ?b then _ else _ ] ⇒
    destruct b eqn: e
  end.

Ltac destruct_if' :=
  let e := fresh "e" in
  destruct_if e.

Ltac destruct_ifs :=
  repeat destruct_if'.

Ltac destruct_bool b :=
  lazymatch b with
  | negb ?bdestruct_bool b
  | ?b && ?cdestruct_bool b
  | _let e := fresh "e" in destruct b eqn: e
  end.

Ltac d_if :=
  lazymatch goal with
  | |- context [ if ?b then _ else _ ] ⇒
    destruct_bool b
  end.

Section Inb.

  Context {A} (eqb : A A bool).

  Definition inb (a : A) (l : list A) :=
    existsb (eqb a) l.

  Definition inclb (l l' : list A) : bool :=
    forallb (λ x, inb x l') l.

End Inb.

Notation "#| l |" := (length l).

Lemma nth_error_app_r :
   A (l l' : list A) n,
    nth_error (l ++ l') (#|l| + n) = nth_error l' n.
Proof.
  intros A l l' n.
  induction l as [| a l ih] in l', n |- ×.
  - reflexivity.
  - cbn. apply ih.
Qed.

Lemma nth_skipn :
   A (l : list A) x y d,
    nth (x + y) l d = nth y (skipn x l) d.
Proof.
  intros A l x y d.
  induction l as [| a l ih] in x, y |- ×.
  1:{ destruct x, y. all: reflexivity. }
  destruct x, y. all: cbn. 1,2: reflexivity.
  - apply ih.
  - apply ih.
Qed.

Lemma nth_error_skipn :
   A (l : list A) x y,
    nth_error l (x + y) = nth_error (skipn x l) y.
Proof.
  intros A l x y.
  induction l as [| a l ih] in x, y |- ×.
  1:{ destruct x, y. all: reflexivity. }
  destruct x, y. all: cbn. 1,2: reflexivity.
  - apply ih.
  - apply ih.
Qed.

Lemma nth_app_r :
   A (l l' : list A) d n,
    nth (#|l| + n) (l ++ l') d = nth n l' d.
Proof.
  intros A l l' d n.
  induction l as [| a l ih] in l', n |- ×.
  - reflexivity.
  - cbn. apply ih.
Qed.

Definition option_bind {A B} (o : option A) (f : A option B) :=
  match o with
  | Some xf x
  | NoneNone
  end.

Definition whenSome {A} (P : A Prop) (o : option A) :=
  match o with
  | Some xP x
  | NoneTrue
  end.