Inductive IO_event : Type -> Type :=
| ERead : IO_event int
| EWrite (c : int) : IO_event unit.
Definition read : itree IO_event int := embed ERead.
Definition write (c : int) : itree IO_event unit := embed (EWrite c).
Definition IO_itree := itree IO_event unit.
(* We need a layer of equivalence to allow us to use the monad laws. *)
Definition ITREE (tr : IO_itree) := EX tr' : _, !!(eq_utt tr tr') &&
has_ext tr'.

(* Specifications: *)
Lemma has_ext_ITREE : forall tr, has_ext tr |-- ITREE tr.
Definition putchar_spec :=
WITH c : int, k : IO_itree
PRE [ 1%positive OF tint ]
PROP ()
LOCAL (temp 1%positive (Vint c))
SEP (ITREE (write c ;; k))
POST [ tint ]
PROP ()
LOCAL (temp ret_temp (Vint c))
SEP (ITREE k).