Since you called it “Maybe monad”, I assume you’re looking at OCaml’s parallel to Haskell’s. So let’s go at this step-by-step…
first of all the data type:
data Maybe a = Nothing | Just a
is the same as OCaml’s option
, already defined in stdlib
type 'a option = None | Some of 'a
second of all, the monad interface:
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
which can be defined as an OCaml module-type
module type Monad = sig
type 'a m
val (>>=) : 'a m -> ('a -> 'b m) -> 'b m
val return : 'a -> 'a m
end
third of all, the implementation (there are sugars here that I skipped):
instance Monad Maybe where
(>>=) m f = case m of
Nothing -> Nothing
Just x -> f x
return x = Just x
which we can translate to OCaml
module Option_monad : Monad = struct
type 'a m = 'a option
let (>>=) m f = match m with
| Some x -> f x
| None -> None
let return x = Some x
end
OCaml’s Option
module has return
under a different name: some
, and (>>=)
under a function name not an operator: bind
.
fourth of all, notation… In Haskell, your sugar is the do-notation:
nine :: Maybe Int
nine = do
x <- return 4
return (5 + x)
while in OCaml, your sugar is the let-operators
module Option_monad_sugar = struct
let (let*) = Option_monad.(>>=) (* or Option.bind *)
let return = Option_monad.return (* or Option.some *)
end
let nine = Option_monad_sugar.(
let* x = return 4 in
return (5 + x)
)
notice that what a “monad” is from a programming perspective is just an interface with implied discipline (Haskell does not prove that every instance follows that discipline, but you should)…
That discipline is that every instance of Monad
should follow three rules (in pseudo-ocaml, with ≡
meaning equivalence):
forall m, f, g, x:
(* 1 *) m >>= return ≡ m
(* 2 *) return x >>= f ≡ f x
(* 3 *) (m >>= f) >>= g ≡ m >>= (fun x -> f x >>= g)
if your implementation of the Monad
interface holds all these rules true, it’s considered “monadic”.
Try to write assertions in actual OCaml with the Option_monad
implementation to see if it’s monadic.
fifth of all, what all this means…
You’re free to use OCaml’s option
or Haskell’s Maybe
without paying any attention to the Monad
interface, and still write safe software that can express a “null” value. What the interface offers you is what any other interface offers you: a way to write functions that do not care about the actual implementation being Option
, or MyCoolModule
. What giving it a mathematical name like “Monad” does is just attach implications from such field (the three rules) which you can use to your advantage or ignore.