I'm getting myself familiar with monad transformers in OCaml using monads library.
Here is an example I'm working with:
open Base
open Stdio
open Monads.Std
module St = struct
include Monad.State.T1 (Monoid.Int) (Monad.Ident)
include Monad.State.Make (Monoid.Int) (Monad.Ident)
end
module W = Monad.Writer.Make (Monoid.String) (St)
let w_example =
let open W in
let writer =
let* () = write "A" in
let* () = lift (St.put 42) in
return (-1)
in
let w_result = run writer in
let s_result, state = St.run w_result 0 in
s_result, state
let () = printf "((%d, %s), %d)\n" (fst (fst w_example)) (snd (fst w_example)) (snd w_example)
I have two questions:
- Is there an automatic way to retrieve the result
-1, the logA, and the state42all at once without manuallyrun-ing all the composed monads inwards? - To
puta new state intoWmonad, I needed to separateStmodule in order to exposeSt.put.Wdoes not haveputexposed. Is there a way if I just went with
module W =
Monad.Writer.Make
(Monoid.String)
(struct
include Monad.State.T1 (Monoid.Int) (Monad.Ident)
include Monad.State.Make (Monoid.Int) (Monad.Ident)
end)
without a separate St?
runfunction that goes through all the layer of the monad stack:It is also a good place to define a more human-friendly return type like
Monad.State.Make (Monoid.Int) (Monad.Ident)before using itsputfunction anyway. Trying to avoid naming theStmonad would be mostly unpractical.