Skip to content

Instantly share code, notes, and snippets.

@leque
Last active September 30, 2021 07:44
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save leque/147095bd992df351305a to your computer and use it in GitHub Desktop.
Save leque/147095bd992df351305a to your computer and use it in GitHub Desktop.
Freer monad in OCaml
(*
Requirement: higher, ppx_deriving.show
*)
(*
Lightweight higher-kinded polymorphism
https://ocamllabs.github.io/higher/lightweight-higher-kinded-polymorphism.pdf
*)
open Higher
(*
Freer Monads, More Extensible Effects
http://okmij.org/ftp/Haskell/extensible/more.pdf
*)
type (_, _) freer =
| Pure : 'a -> ('a, 'f) freer
| Impure : ('a, 'f) app * ('a -> ('b, 'f) freer) -> ('b, 'f) freer
let pure v = Pure v
let rec (>>=) m k =
match m with
| Pure v -> k v
| Impure (v, k') -> Impure (v, fun x -> k' x >>= k)
let lift m = Impure (m, pure)
let rec sequence = function
| [] -> pure []
| mx::mxs ->
mx >>= fun x ->
sequence mxs >>= fun xs ->
pure (x :: xs)
let rec sequence_ = function
| [] -> pure ()
| mx::mxs ->
mx >>= fun _ ->
sequence_ mxs
(* List monad *)
module L = Newtype1(struct type 'a t = 'a list end)
let flat_map f xs = List.flatten (List.map f xs)
let llift v = v |> L.inj |> lift
let rec run_list = function
| Pure v -> [v]
| Impure (v, k) -> flat_map (fun x -> run_list @@ k x) (L.prj v)
let () = run_list begin
llift [1; 2; 3] >>= fun v ->
llift ['a'; 'b'; 'c'] >>= fun w ->
pure (v, w)
end |> [%derive.show: (int * char) list] |> print_endline
let () = run_list begin
sequence [pure 1; pure 2; pure 3]
end |> [%derive.show: int list list] |> print_endline
(* Option monad *)
module O = Newtype1(struct type 'a t = 'a option end)
let bind_o m k =
match m with
| Some v -> k v
| None -> None
let olift v = v |> O.inj |> lift
let rec run_option = function
| Pure v -> Some v
| Impure (v, k) -> bind_o (O.prj v) (fun x -> run_option @@ k x)
let print v =
v |> [%derive.show: int list option] |> print_endline
let () = run_option begin
sequence [pure 1; pure 2; pure 3]
end |> print
let () = run_option begin
sequence [pure 1; olift None; pure 3]
end |> print
@Yahyakpj11
Copy link

How la

@NikolaGamer
Copy link

i get robux

@DeezNutzBoi
Copy link

how do u get the roux?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment