SimpleIO.IO_Monad
The IO monad
The result type of unsafe_run.
For example, to extract a program main : IO unit to
a file named main.ml:
Definition exe : io_unit := unsafe_run main.
Extraction "main.ml" exe.
Definition exe : io_unit := unsafe_run main.
Extraction "main.ml" exe.
All identifiers are meant to be used qualified.
Fixpoint combinator.
Delay eager evaluation.
Some IO actions can be expensive closures.
delay_io allows the computation of the closure to
happen during execution, instead of eagerly during the
definition of the IO action.
Apply a pure function to the result of an action.
Infinite stateful loop.
Definition loop : forall {a void}, (a -> IO a) -> (a -> IO void) :=
fun _ _ f => fix_io (fun k x => bind (f x) k).
fun _ _ f => fix_io (fun k x => bind (f x) k).
While loop. Stops once the output is None.
Definition while_loop : forall {a}, (a -> IO (option a)) -> (a -> IO unit) :=
fun _ f => fix_io (fun k x => bind (f x) (fun y' =>
match y' with
| None => ret tt
| Some y => k y
end)).
fun _ f => fix_io (fun k x => bind (f x) (fun y' =>
match y' with
| None => ret tt
| Some y => k y
end)).
Module Notations.
Delimit Scope io_scope with io.
Notation "c >>= f" := (bind c f)
(at level 58, left associativity) : io_scope.
Notation "f =<< c" := (bind c f)
(at level 61, right associativity) : io_scope.
Notation "x <- c1 ;; c2" := (bind c1 (fun x => c2))
(at level 61, c1 at next level, right associativity) : io_scope.
Notation "e1 ;; e2" := (_ <- e1%io ;; e2%io)%io
(at level 61, right associativity) : io_scope.
Notation delay io := (delay_io (fun _ => io)).
Open Scope io_scope.
End Notations.
Axiom bind_ret :
forall {a b} (x : a) (k : a -> IO b), bind (ret x) k = k x.
Axiom ret_bind : forall {a} (m : IO a), bind m ret = m.
Axiom bind_bind :
forall {a b c} (m : IO a) (k : a -> IO b) (h : b -> IO c),
bind (bind m k) h = bind m (fun x => bind (k x) h).
Axiom bind_ext : forall {a b} (m : IO a) (k k' : a -> IO b),
(forall x, k x = k' x) -> bind m k = bind m k'.
Run!
Run an IO action, ignoring the result.
Run an IO action to produce a result.
This can break referential transparency quite badly.
(* CPS prevents stack overflows. *)
(* forall r, (a -> r) -> r *)
Extract Constant IO "'a" => "('a -> Obj.t) -> Obj.t".
Extract Constant ret => "fun a k -> (k a : Obj.t)".
Extract Constant bind => "fun io_a io_b (k : _ -> Obj.t) -> (io_a (fun a -> (io_b a k : Obj.t)) : Obj.t)".
Extract Constant fix_io => "fun f -> let rec go a (k : _ -> Obj.t) : Obj.t = f go a k in go".
Extract Constant delay_io => "fun f (k : _ -> Obj.t) -> (f () k : Obj.t)".
Extract Inlined Constant io_unit => "unit".
Extract Constant unsafe_run => "fun io -> Obj.magic io (fun () -> ())".
Extract Constant unsafe_run' => "fun io -> Obj.magic io (fun _ -> ())".
Extract Constant very_unsafe_eval => "fun io -> Obj.magic io (fun x -> x)".
End IO.