Definition io_specs :=
[(_getchar, getchar_spec); (_putchar, putchar_spec)].
Definition ext_link := ext_link_prog prog.
(* Should we really need a concrete user program in order to build enough of an external_specification for the juicy_dry proof? *)
Definition io_ext_spec
:=
add_funspecs_rec
ext_link
(ok_void_spec IO_itree).(@OK_ty)
(ok_void_spec IO_itree).(@OK_spec)
io_specs.
Definition getchar_pre (m : mem) (k : int -> IO_itree) (z : IO_itree) :=
(z = (r <- read;; k r))%eq_utt.
Definition getchar_post (m0 m : mem) r (k : int -> IO_itree) (z : IO_itree) :=
m0 = m /\ - two_p 7 <= Int.signed r <= two_p 7 - 1 /\ z = k r.
Definition putchar_pre (m : mem) c (k : IO_itree) (z : IO_itree) :=
(z = (write c;; k))%eq_utt.
Definition putchar_post (m0 m : mem) r (c : int) (k : IO_itree) (z : IO_itree) :=
m0 = m /\ r = c /\ z = k.
Program Definition io_dry_spec : external_specification mem external_function IO_itree.

Lemma ghost_join_nth : forall (a b c : ghost) n, join a b c ->
join (nth n a None) (nth n b None) (nth n c None).