Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Bannerets/7440667f63437497d7086e0fa220a68e to your computer and use it in GitHub Desktop.
Save Bannerets/7440667f63437497d7086e0fa220a68e to your computer and use it in GitHub Desktop.

Comparison of abstracting over monads in OCaml and Haskell.

Defining monads in OCaml first:

module type Monad = sig
  type 'a t
  val return : 'a -> 'a t
  val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
end

module OptionMonad = struct (* `implicit module` for modular implicits *)
  type 'a t = 'a option
  let return = Option.some
  let (>>=) = Option.bind
end

module ListMonad = struct (* `implicit module` for modular implicits *)
  type 'a t = 'a list
  let return a = [a]
  let (>>=) x f = List.concat_map f x
end

Current OCaml:

module PairM (M : Monad) = struct
  let run x y =
    M.(x >>= fun x' -> y >>= fun y' -> return (x', y'))
end

let options_pairs =
  let module PairOption = PairM(OptionMonad) in
  PairOption.run (Some 1) (Some "a")

let list_pairs =
  let module PairList = PairM(ListMonad) in
  PairList.run [1; 2; 3] [true; false]

vs Haskell:

pairM :: Monad m => m a -> m b -> m (a, b)
pairM x y = x >>= \x' -> y >>= \y' -> return (x', y')

option_pairs = pairM (Just 1) (Just "a")

list_pairs = pairM [1, 2, 3] [True, False]

vs OCaml with modular explicits:

let pairM {M : Monad} x y = M.(x >>= fun x' -> y >>= fun y' -> return (x', y'))

let option_pairs = pairM {module OptionMonad} (Some 1) (Some "a")

let list_pairs = pairM {module ListMonad} [1; 2; 3] [true; false]

vs OCaml with modular implicits:

let pairM {M : Monad} x y = M.(x >>= fun x' -> y >>= fun y' -> return (x', y'))

let option_pairs = pairM (Some 1) (Some "a")

let list_pairs = pairM [1; 2; 3] [true; false]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment