ITree.Interp.HandlerFacts

Theorems for ITree.Interp.Handler



Section HandlerCategory.

Local Opaque eutt ITree.bind interp ITree.trigger.

Instance Proper_Cat_Handler {A B C}
  : @Proper (Handler A B Handler B C Handler A C)
            ( )
            cat.
Proof.
  cbv; intros.
  apply eutt_interp; auto.
Qed.


Instance CatIdR_Handler : CatIdR Handler.
Proof.
  cbv; intros.
  rewrite interp_trigger_h. reflexivity.
Qed.


Instance CatIdL_Handler : CatIdL Handler.
Proof.
  cbv; intros.
  rewrite interp_trigger.
  reflexivity.
Qed.


Instance CatAssoc_Handler : CatAssoc Handler.
Proof.
  cbv; intros.
  rewrite interp_interp.
  reflexivity.
Qed.


Global Instance Category_Handler : Category Handler.
Proof.
  split; typeclasses eauto.
Qed.


Global Instance InitialObject_Handler : InitialObject Handler .
Proof.
  cbv; contradiction.
Qed.


Instance Proper_Case_Handler {A B C}
  : @Proper (Handler A C Handler B C Handler (A +' B) C)
            ( )
            case_.
Proof.
  cbv; intros.
  destruct (_ : _ _ _); auto.
Qed.


Instance CaseInl_Handler : CaseInl Handler .
Proof.
  cbv; intros.
  rewrite interp_trigger.
  reflexivity.
Qed.


Instance CaseInr_Handler : CaseInr Handler .
Proof.
  cbv; intros.
  rewrite interp_trigger.
  reflexivity.
Qed.


Instance CaseUniversal_Handler : CaseUniversal Handler .
Proof.
  cbv; intros.
  destruct (_ : _ _ _).
  - rewrite H, interp_trigger. reflexivity.
  - rewrite , interp_trigger. reflexivity.
Qed.


Global Instance Coproduct_Handler : Coproduct Handler .
Proof.
  split; typeclasses eauto.
Qed.


Local Opaque Recursion.interp_mrec.

Instance Proper_Iter_Handler {A B}
  : @Proper (Handler A (A +' B) Handler A B)
            ( )
            iter.
Proof.
  repeat intro.
  apply Proper_interp_mrec; auto.
Qed.


Instance IterUnfold_Handler : IterUnfold Handler .
Proof.
  cbv; intros.
  rewrite interp_mrec_as_interp.
  reflexivity.
Qed.


Instance IterNatural_Handler : IterNatural Handler .
Proof.
  cbv; intros.
  pattern f.
  match goal with
  | [ |- ?G ?f ] ⇒
    enough (HHH : G (fun T eTau (f T e))); cbn in ×
  end.
  { etransitivity; [etransitivity; [|eapply HHH] |]; clear.
    - symmetry. apply euttge_sub_eutt, euttge_interp.
      + reflexivity.
      + apply euttge_interp_mrec; repeat intro; apply tau_euttge.
    - apply euttge_sub_eutt, euttge_interp_mrec.
      + intros ? ?. apply euttge_interp.
        × reflexivity.
        × apply tau_euttge.
      + rewrite tau_euttge. reflexivity.
  }
  match goal with
  | [ |- _ _ (_ _ _ (_ ? _ _)) ] ⇒
    remember as h eqn:EQh
    (* h is pretty big and duplicating it slows down the display of the goal,
       so we try to rewrite with EQh only when necessary. *)

  end.
  remember (Tau (f T )) as t eqn:tmp_t. clear tmp_t.
  revert t; einit; ecofix CIH; intros t.
  rewrite (itree_eta t).
  destruct (observe t).
  - rewrite unfold_interp_mrec; cbn.
    rewrite 2 interp_ret.
    rewrite unfold_interp_mrec.
    reflexivity.
  - rewrite unfold_interp_mrec; cbn.
    rewrite 2 interp_tau.
    rewrite (unfold_interp_mrec _ _ (Tau _)); cbn.
    estep.
  - rewrite unfold_interp_mrec; cbn.
    rewrite interp_vis.
    destruct e; cbn.
    + rewrite interp_tau.
      rewrite 2 interp_mrec_bind, interp_bind.
      subst h; cbn.
      rewrite interp_trigger.
      rewrite unfold_interp_mrec; cbn.
      rewrite interp_mrec_trigger; cbn.
      unfold Recursion.mrec.
      rewrite !interp_tau.
      rewrite (unfold_interp_mrec _ _ (Tau _)); cbn.
      rewrite !bind_tau.
      etau. rewrite tau_euttge, interp_bind, 2 interp_mrec_bind.
      setoid_rewrite (tau_euttge (interp _ _)).
      rewrite interp_bind.
      auto with paco.
    + rewrite interp_vis.
      rewrite interp_mrec_bind.
      subst h; cbn.
      Local Transparent eutt.
      ebind. apply (pbc_intro_h _ _ _ _ _ eq).
      { rewrite interp_mrec_as_interp, interp_interp.
        rewrite interp_id_h at 1.
        eapply eutt_interp; try reflexivity.
        intros ? ?.
        rewrite interp_trigger; cbn.
        reflexivity. }
      intros ? _ [].
      rewrite (unfold_interp_mrec _ _ (Tau _)); cbn.
      etau.
      rewrite tau_euttge.
      auto with paco.
Qed.


Section DinatSimulation.

Context {A B C : Type Type}.
Context (f0 : A ~> itree (B +' C)) (g0 : B ~> itree (A +' C)).
Context {R : Type}.

Context (f := fun T eTau ( T e)) (g := fun T eTau ( T e)).

Inductive interleaved
  : itree (A +' C) R itree (B +' C) R Prop :=
| interleaved_Ret r : interleaved (Ret r) (Ret r)
| interleaved_Left {U} (t : itree _ U) k1 k2 :
    ( (x : U), interleaved ( x) ( x))
    interleaved (interp (handle (case_ g inr_)) t >>= ) (t >>= )
| interleaved_Right {U} (t : itree _ U) k1 k2 :
    ( (x : U), interleaved ( x) ( x))
    interleaved (t >>= ) (interp (handle (case_ f inr_)) t >>= )
.
#[local] Hint Constructors interleaved : itree.

Let hg := @case_ _ Handler _ _ _ _ _ g inr_.
Let hf := @case_ _ Handler _ _ _ _ _ f inr_.

Theorem interleaved_mrec : t1 t2,
    interleaved
    Recursion.interp_mrec (cat f (case_ g inr_))
   Recursion.interp_mrec (cat g (case_ f inr_)) .
Proof.
  einit; ecofix CIH; intros.
  induction .
  - rewrite 2 unfold_interp_mrec; cbn. estep.
  - rewrite (itree_eta t); destruct (observe t).
    + rewrite interp_ret, 2 bind_ret_l. auto.
    + rewrite interp_tau, 2 bind_tau, 2 unfold_interp_mrec; cbn.
      estep.
    + rewrite interp_vis, bind_vis.
      rewrite bind_bind.
      rewrite (unfold_interp_mrec _ _ (Vis _ _)); cbn.
      destruct e; cbn. setoid_rewrite (tau_euttge (interp _ _)).
      × unfold cat at 3, Cat_Handler at 3, Handler.cat.
        change (g X b) with (Tau ( X b)).
        rewrite bind_tau, unfold_interp_mrec; cbn.
        etau. rewrite tau_euttge. ebase.
      × unfold inr_, Inr_sum1_Handler, Handler.inr_, Handler.htrigger.
        rewrite bind_trigger.
        rewrite unfold_interp_mrec; cbn.
        evis; intros; etau. rewrite tau_euttge. ebase.
  - rewrite (itree_eta t); destruct (observe t).
    + rewrite interp_ret, 2 bind_ret_l. auto.
    + rewrite interp_tau, 2 bind_tau, 2 unfold_interp_mrec; cbn.
      estep.
    + rewrite interp_vis, bind_vis.
      rewrite bind_bind.
      rewrite (unfold_interp_mrec _ _ (Vis _ _)); cbn.
      destruct e; cbn. setoid_rewrite (tau_euttge (interp _ _)).
      × unfold cat at 2, Cat_Handler at 2, Handler.cat.
        change (f X a) with (Tau ( X a)).
        rewrite !bind_tau, (unfold_interp_mrec _ _ (Tau _)); cbn.
        etau. rewrite tau_euttge. ebase.
      × unfold inr_, Inr_sum1_Handler, Handler.inr_, Handler.htrigger.
        rewrite bind_trigger.
        rewrite unfold_interp_mrec; cbn.
        evis; intros; etau. rewrite tau_euttge. ebase.
Qed.


End DinatSimulation.

Local Opaque eutt.

Instance IterDinatural_Handler : IterDinatural Handler .
Proof.
  cbv; intros a b c T .
  pose (f := fun T eTau ( T e)). pose (g := fun T eTau ( T e)).
  enough (
      Recursion.interp_mrec (cat f (case_ g inr_))
                            (interp (case_ g inr_) (f _ ))
     interp (mrecursive (cat g (case_ f inr_))) (f _ )).
  { cbv in H. etransitivity; [etransitivity; [|apply H]|]; clear H.
    - symmetry. apply euttge_sub_eutt, euttge_interp_mrec.
      1: intros ? ?.
      1,2: rewrite tau_euttge; apply euttge_interp; try reflexivity.
      1,2: intros ? []; [apply tau_euttge| reflexivity].
    - apply euttge_sub_eutt, euttge_interp; [ | apply tau_euttge].
      intros ? []; try reflexivity.
      rewrite tau_euttge. apply euttge_interp_mrec.
      intros ? ?.
      rewrite tau_euttge.
      all: apply euttge_interp; try reflexivity.
      all: intros ? []; [apply tau_euttge | reflexivity].
  }
  rewrite interp_mrec_as_interp.

  rewrite (bind_ret_r (interp _ _)).
  rewrite (bind_ret_r (f _ )) at 2.

  apply interleaved_mrec.
  do 2 constructor.
Qed.


Import Recursion.

Instance IterCodiagonal_Handler : IterCodiagonal Handler .
Proof.
  cbv; intros a b T x.
  remember ( T x) as t eqn:EQt; clear.
  pose (f := fun T eTau ( T e)).
  enough (interp_mrec (fun _ dinterp_mrec f (f _ d))
                      (interp_mrec f t)
           interp_mrec (fun _ einterp (fun _ ab
                                              match ab with
                                              | inl1 xITree.trigger (inl1 x)
                                              | inr1 yITree.trigger y
                                              end) (f _ e))
                        (interp (fun _ ab
                                   match ab with
                                   | inl1 xITree.trigger (inl1 x)
                                   | inr1 yITree.trigger y
                                   end) t)).
  { subst f. etransitivity; [etransitivity; [| apply H] |]; clear H.
    - symmetry. apply euttge_sub_eutt, euttge_interp_mrec.
      + intros ? ?. apply euttge_interp_mrec; try apply tau_euttge.
        intros ? ?. apply tau_euttge.
      + apply euttge_interp_mrec; repeat intro; reflexivity + rewrite tau_euttge.
        reflexivity.
    - apply euttge_sub_eutt, euttge_interp_mrec; repeat intro;
        apply euttge_interp; try reflexivity.
      apply tau_euttge.
  }
  revert t. einit; ecofix CIH. intros.
  rewrite (itree_eta t); destruct (observe t); cbn.
  all: rewrite (unfold_interp_mrec _ _ (go _)), unfold_interp; cbn.
  1,2: rewrite unfold_interp_mrec; cbn.
  1,2: rewrite (unfold_interp_mrec _ _ (go _)); estep.
  destruct e.
  - rewrite (interp_mrec_bind _ (ITree.trigger _)).
    rewrite interp_mrec_trigger; cbn.
    unfold Recursion.mrec.
    remember (f X ) as fxa eqn:Hfxa; unfold f in Hfxa; subst fxa.
    rewrite interp_tau, unfold_interp_mrec; cbn.
    rewrite (unfold_interp_mrec _ _ (Tau _)); cbn.
    rewrite !bind_tau.
    etau.
    rewrite tau_euttge. setoid_rewrite tau_euttge.
    rewrite interp_mrec_bind, interp_bind.
    auto with paco.
  - rewrite bind_trigger.
    setoid_rewrite tau_euttge.
    rewrite 2 unfold_interp_mrec; cbn.
    destruct s; estep.
    rewrite interp_mrec_bind, interp_bind.
    auto with paco.
Qed.


Global Instance Iterative_Handler : Iterative Handler .
Proof.
  split; typeclasses eauto.
Qed.


End HandlerCategory.