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]