I have the following:
module type MONAD_SIG =
sig
type 'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
end
module IdMonad : MONAD_SIG =
struct
type 'a t = Id of 'a
let return v = Id v
let bind (Id v) f = f v
let (>>=) = bind (* always the case *)
end
type term = Const of int | Div of term * term
let e1 = Div (Div (Const 1972, Const 2), Const 23)
let e2 = Div (Const 1, Const 0)
module EvalIdMonad = struct
include IdMonad
let divM a b = return (a / b) (* will be different for each monad; type ?? *)
let evalM t = (* will be the same across all monads; type ?? *)
let rec evalMrec t =
match t with
| Const c -> return c
| Div(a,b) -> evalMrec a >>= fun n -> evalMrec b >>= fun d -> divM n d
in evalMrec t
end
let _ = EvalIdMonad.evalM e1
This: evalMrec a >>= fun n -> evalMrec b >>= fun d -> divM n d
I have trouble understanding what it means or how it evaluates given that there is no parenthesis at least to illustrate.
What I get is that, first let's assume we reach the recursive basis and we have this:
return c >>= fun n -> return c' >>= fun d -> divM n d
, how this will work? My guess is that we go innermost first, so, return c' >>= fun d -> divM n d
evaluates first, and we get divM n c'
and then return c >>= fun n -> divM n c'
will return divM c c'
, is that correct?
Also, can you illustrate how monad is helping here?
Since the monad that you are using is the identity monad, it is not helping in any way, it is just a layer of syntactic boilerplate. In particular, >>=
is just a version of |>
(left-to-right) function evaluation that destructure the Id _
constructor on this left side
evalMrec a >>= fun n -> evalMrec b >>= fun d -> divM n d
reads
evalMrec a |> (fun (Id n) ->
evalMrec b |> (fun (Id d) ->
divM n d
)
)
which can be rewritten using let as
let Id n = evalMRec a in
let Id d = evalMRec b in
divM n d
Presumably, this is just an intermediary step in your textbook/homework before moving to more interesting examples. But you should not spend too much time trying to find deep meaning, at this point there are none.
Similarly
return c >>= fun n -> return c' >>= fun d -> divM n d
reads
(return c) >>= (fun n -> return c' >>= fun d -> divM n d)
and like any operators both sides of the operators are evaluated before the operator is applied to the results.