Module Tree.
Variant nd : Type -> Type :=
| Or : nd bool.
Definition or {R : Type} (t1 t2 : itree nd R) : itree nd R :=
Vis Or (fun b : bool => if b then t1 else t2).
(* Flip a coin *)
Definition choice {E} `{nd -< E} : itree E bool := trigger Or.
Definition eval_def := (fun (c : com) =>
match c with
| loop c =>
(b <- choice;;
if b : bool
then Ret tt
else (trigger (Call c);; trigger (Call (loop c))))%itree
| choose c1 c2 =>
(b <- choice;;
if b : bool
then trigger (Call c1)
else trigger (Call c2))%itree
| (t1 ;; t2)%com => (trigger (Call t1);; trigger (Call t2))%itree
| skip => Ret tt
end
).
Definition eval : com -> itree nd unit := rec eval_def.
(* [itree] semantics of [one_loop]. *)
Definition one_loop_tree : itree nd unit :=
rec (fun _ : unit =>
(* note: [or] is not allowed under [mfix]. *)
b <- choice;;
if b : bool then
Ret tt
else
trigger (Call tt))%itree tt.

(* SAZ: the [~] notation for eutt wasn't working here. *)
Lemma eval_one_loop : eval one_loop ≈ one_loop_tree.