Hi, I am having this Id monad:

```
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
module Term = struct
type term = Const of int | Div of term * term | Add of term * term | Mlt of term * term
let div_answer = Div(Div(Const 1972, Const 2), Const 23)
let add_answer = Add(Add(Const 1972, Const 2), Const 23)
let mlt_answer = Mlt(Mlt(Const 1972, Const 2), Const 23)
let mix_answer = Mlt(mlt_answer, add_answer)
let error = Div(Const 1, Const 0)
end
module type MONAD_SIG_ARITHMETIC =
sig
include MONAD_SIG
val divM : int -> int -> int t
val addM : int -> int -> int t
val mltM : int -> int -> int t
end
module IdMonadArithmetic : MONAD_SIG_ARITHMETIC = struct
include IdMonad
let divM a b = return (a / b)
let addM a b = return (a + b)
let mltM a b = return (a * b)
end
module MakeEvalMonad(Q : MONAD_SIG_ARITHMETIC) = struct
include Term
open Q
let evalM t =
let rec evalMrec t =
match t with
| Const c -> return c
| Div(a,b)-> evalMrec a >>= (fun n -> evalMrec b >>= (fun d -> Q.divM n d))
| Add(a,b)-> evalMrec a >>= (fun n -> evalMrec b >>= (fun d -> Q.addM n d))
| Mlt(a,b)-> evalMrec a >>= (fun n -> evalMrec b >>= (fun d -> Q.mltM n d))
in return t >>= evalMrec
end
module EvalIdMonad = MakeEvalMonad(IdMonadArithmetic)
(* open EvalIdMonad *)
let _ = EvalIdMonad.evalM EvalIdMonad.mlt_answer
```

And I am using functor for `MakeEvalMonad`

, however, when I am trying to run `let _ = EvalIdMonad.evalM EvalIdMonad.mlt_answer`

, I get this `- : int IdMonadArithmetic.t = <abstr>`

instead of `Id 90712`

, what is the problem? (Thanks!)

This is hiding the type definition because `MONAD_SIG_ARITHMETIC`

exposes only an abstact type `'a t`

. You can remove the module type annotation to get the expected result. The compiler automatically checks the module type conformance.

You can also simplify the code by defining:

```
module IdMonad = struct
type 'a t = 'a
...
```

And so on.

I still get the same result: `- : int IdMonadArithmetic.t = <abstr>`

.

What I did was just doing this `module IdMonadArithmetic = struct include IdMonad ...`

. I did it before asking because that’s what I thought.

I even tried to simply the code like below, and it still gives: `- : int IdMonad.t = <abstr>`

```
module Term = struct
type term = Const of int | Div of term * term | Add of term * term | Mlt of term * term
let div_answer = Div(Div(Const 1972, Const 2), Const 23)
let add_answer = Add(Add(Const 1972, Const 2), Const 23)
let mlt_answer = Mlt(Mlt(Const 1972, Const 2), Const 23)
let mix_answer = Mlt(mlt_answer, add_answer)
let error = Div(Const 1, Const 0)
end
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
val divM : int -> int -> int t
val addM : int -> int -> int t
val mltM : int -> int -> int 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 *)
let divM a b = return (a / b)
let addM a b = return (a + b)
let mltM a b = return (a * b)
end
module MakeEvalMonad(Q : MONAD_SIG) = struct
include Term
open Q
let evalM t =
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))
| Add(a,b)-> evalMrec a >>= (fun n -> evalMrec b >>= (fun d -> addM n d))
| Mlt(a,b)-> evalMrec a >>= (fun n -> evalMrec b >>= (fun d -> mltM n d))
in return t >>= evalMrec
end
module EvalIdMonad = MakeEvalMonad(IdMonad)
(* open EvalIdMonad *)
let _ = EvalIdMonad.evalM EvalIdMonad.mlt_answer
```

I just ran your original code sample after removing two module type annotations and got the desired result:

```
utop # let ans = EvalIdMonad.evalM EvalIdMonad.mlt_answer;;
val ans : int IdMonadArithmetic.t = IdMonadArithmetic.Id 90712
```

Oh I see, which two module annotations please?

There are only two modules in your original code which have module type annotations. They look like this: `module M : T = ...`

It worked now, when I removed the `: MONAD_SIG`

from `module IdMonad : MONAD_SIG = `

, but why is that? I mean, even in the simplified code where an annotation shouldn’t have been a problem.

Same reason as my original reply. Basically the module type annotation hides the internals of the module, including the type definition, and only allows an abstract view of the type from external to the module.

I see, I get it now. Thanks

1 Like

I’ve noticed time and time again that this kind of sealing with signatures often just gets in my way. I have to recover transparency later with something like:

```
module IDMonad : Monad with type 'a t = 'a
= struct ... end
```

which gets repetitive and has its own drawbacks. Or by removing signatures like yawaramin did.

I feel like it’s better to be specific only in what you accept… That is, use signature declaration only for functor arguments, and leave modules open. If you want the assurance of interface-conformance, I’ve resorted to do that in a testing file:

```
module _ = (ID : Monad)
```

IDK if this is the most ideal, or if I’m just inexperienced with software engineering practices and committing atrocities, but it has simplified my code a bit at the module language and lowered the level of verbosity.

Very nice, I think it must deliver a good result for those who are into long projects in Ocaml.