Skip to content

Instantly share code, notes, and snippets.

@nvanderw
Last active October 8, 2019 20:24
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save nvanderw/7029997 to your computer and use it in GitHub Desktop.
Save nvanderw/7029997 to your computer and use it in GitHub Desktop.
IO Monad in OCaml
module type FUNCTOR = sig
type 'v f
val map : ('a -> 'b) -> 'a f -> 'b f
end
module type MONAD = sig
type 'v f
val map : ('a -> 'b) -> 'a f -> 'b f
val pure : 'a -> 'a f
val join : ('a f) f -> 'a f
end
(* Monad transformers! *)
module type MONADTRANS = functor (M: MONAD) -> sig
type 'v f
val lift : 'a M.f -> 'a f
end
(* Creates a type 'a IO, which is a wrapper around (unit -> 'a) *)
module IOMonad = struct
type 'v f = IO of (unit -> 'v)
let map f m = let (IO m') = m in IO (fun () -> f (m' ()))
let pure x = IO (fun () -> x)
let join m = IO (fun () -> let (IO m') = m in let (IO m') = m' () in m' ())
let runIO m = let (IO m') = m in m'
end
module MonadUtil = functor (Monad: MONAD) -> struct
type 'a f = 'a Monad.f
let bind m f = Monad.join (Monad.map f m)
let seq m n = bind m (fun _ -> n)
let ap fm mx = bind fm (fun f -> Monad.map f mx)
let rec while_ cond action =
let (>>=) = bind in
let (>>) = seq in
cond >>= fun c ->
if c
then action >> while_ cond action
else Monad.pure ()
let until cond action = while_ (Monad.map not cond) action
let forever action = while_ (Monad.pure true) action
end
module IOUtil = MonadUtil(IOMonad)
let main =
let (>>) = IOUtil.seq in
let mprint_string s = IOMonad.IO (fun () -> print_string s) in
IOUtil.forever begin
mprint_string "Hello, " >>
mprint_string "world!\n"
end
let _ = IOMonad.runIO main ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment