Section CategoryLaws.
Context {E : Type -> Type}.
(** *** [compose_ktree] respect eq_ktree *)
Global Instance eq_ktree_compose {A B C} :
@Proper (ktree E A B -> ktree E B C -> _) (eq2 ==> eq2 ==> eq2) cat.
(** *** [compose_ktree] is associative *)
Global Instance CatAssoc_ktree : CatAssoc (ktree E).
(** *** [id_ktree] respect identity laws *)
Global Instance CatIdL_ktree : CatIdL (ktree E).
Global Instance CatIdR_ktree : CatIdR (ktree E).
Global Instance Category_ktree : Category (ktree E).
Global Instance InitialObject_ktree : InitialObject (ktree E) void.
Fact compose_lift_ktree {A B C} (ab : A -> B) (bc : B -> C) :
(lift_ktree_ E _ _ ab >>> lift_ktree bc ⩯ lift_ktree (ab >>> bc))%cat.
Fact compose_lift_ktree_l {A B C D} (f: A -> B) (g: B -> C) (k: ktree E C D) :
(lift_ktree f >>> (lift_ktree g >>> k) ⩯ lift_ktree (g ∘ f) >>> k)%cat.
Fact compose_lift_ktree_r {A B C D} (f: B -> C) (g: C -> D) (k: ktree E A B) :
((k >>> lift_ktree f) >>> lift_ktree g ⩯ k >>> lift_ktree (g ∘ f))%cat.
Fact lift_compose_ktree {A B C}: forall (f:A -> B) (bc: ktree E B C),
lift_ktree f >>> bc ⩯ fun a => bc (f a).
Fact compose_ktree_lift {A B C}: forall (ab: ktree E A B) (g:B -> C),
(ab >>> lift_ktree g)
⩯ (fun a => ITree.map g (ab a)).

Lemma sym_ktree_unfold {A B}:
lift_ktree_ E (A + B) _ swap ⩯ swap.