頭の悪いモナド

モナドを使いやすくするdo構文はHaskellの専売特許です。a >>= (\b -> c >>= (\d >> return e))がdo b <- a; d <- c; return eになります。do構文の何が嬉しいかといいますと、>>=演算子を連ねた場合、本当は匿名関数をネストしまくってるところを、平坦に書けることですね。
では、匿名関数に括弧が要らなかったら……do構文いらないですね。
OCamlは、関数の引数にfunを書く場合は括弧が必要です。しかし演算子の引数にfunを書く場合は括弧が要りません。インデントは意味を持たないため、最後の;;までごそっと匿名関数に入ります。
まさに狙っているとしか思えない文法ですので、それに乗ってHaskellっぽい記述を試みてみました。
先に書いておきますけれども、世の中にはcamlp4を使ったperform構文なんてものもあるそうです。

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

module MonadDefault (Monad: MONAD) = struct
    open Monad;;
    let ( >> ) f g = f >>= (fun _ -> g);;
end;;

module IO = struct
    let ( >>= ) f g = lazy (let v = Lazy.force f in Lazy.force (g v));;
    let return v = lazy v;;
    module Default = MonadDefault (
        struct 
            type 'a t = 'a lazy_t;; 
            let ( >>= ) = ( >>= );; 
            let return = return 
        end
    );;
    let ( >> ) = Default.( >> );;

    let getStr = lazy (read_line ());;
    let putStr s = lazy (print_string s);;
end;;

open IO;;

let rec input_name prompt =
    putStr prompt >>
    getStr >>= fun name ->
    if name = "" then (
        input_name prompt 
    ) else (
        return name
    );;

let main =
    input_name "What's your name? " >>= fun name ->
    putStr "Hello, " >>
    putStr name >>
    putStr "\n";;

Lazy.force main;;

これを実行すると、まずプロンプトが出てきます。何も入力せずにenterを押しますと、次のようになります。

...>ocaml monad.ml
What's your name? enter
What's your name? What's your name? What's your name? What's your name? What's y
our name? What's your name? What's your name? What's your name? What's your name
? What's your name? What's your name? What's your name? What's your name? What's
 your name? What's your name? What's your name? What's your name? What's your na
(……中略……)
me? What's your name? What's your name? What's your name? What's your name? What
's your name? What's your name? What's your name? What's your name? What's your
name? What's your name? What's your name? What's your name? What's your name? Wh
at's your name? What's your name? What's your name? What's your name? What's you
r name? What's your name? What's your name? What's your name? What's your name?
What's your name^C
...>

lazyを使いましたので、一度forceしてしまったらおしまいなんですねー。何度繰り返しても同じ値しか返ってこないわけです。そうか、これが参照透明。(←違う)
lazyから関数にすることで、目的の動作を得ることができました。

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

module MonadDefault (Monad: MONAD) = struct
    open Monad;;
    let ( >> ) f g = f >>= (fun _ -> g);;
end;;

module IO = struct
    type world = Star_platinum_naruhodo_the_world;;
    let getWorld = Star_platinum_naruhodo_the_world;;
    
    let ( >>= ) f g = fun (_: world) -> let v = f getWorld in g v getWorld;;
    let return v = fun (_: world) -> v;;
    module Default = MonadDefault (
        struct 
            type 'a t = world -> 'a;; 
            let ( >>= ) = ( >>= );; 
            let return = return 
        end
    );;
    let ( >> ) = Default.( >> );;

    let getStr = fun (_: world) -> read_line ();;
    let putStr s = fun (_: world) -> print_string s;;
end;;

open IO;;

let rec input_name prompt =
    putStr prompt >>
    getStr >>= fun name ->
    if name = "" then (
        input_name prompt 
    ) else (
        return name
    );;

let main =
    input_name "What's your name? " >>= fun name ->
    putStr "Hello, " >>
    putStr name >>
    putStr "\n";;

main getWorld;;
...>ocaml monad.ml
What's your name?
What's your name? J.J.
Hello, J.J.

...>

IOモナドに限定して言えば、手続き型言語OCamlでは要らないですが、Maybeモナド……も、'a option取ってNoneなら例外投げる関数作れば要らないですが、Exceptionモナド……も、例外あるので要らないですが、Writeモナド……も、破壊的更新ができるので要らないですが、Stateモナド……も、やっぱり破壊的更新ができるので要らないですが、Listモナドでループや探索をしたり、こないだからやってますパーサコンビネータモドキのように、毎回書くのが煩雑なものを裏へ追いやったりといった用途であれば、OCamlでも有意義に使えるのではないかと思います。
尤もHaskellの真似をする必要は全く無くて、>>=風味の動作をする適当な2項演算子を定義しまくるだけで充分でしょうけれども。それをモナドと呼ぶかは知らない。
……今試してみましたがHaskellでも演算子の引数にする時は匿名関数に括弧が要らないような。do構文なんのためにあるんだ。