Basic Module confusion

module type T = {
  type t
  let log: t => unit
}

module M: T = {
  type t = int
  let log = n => Js.log(n)
}

M.log(1) // This is expecting type M.t

Can someone explain to me why this is unhappy? My thinking was that setting the type t = int on module M would be sufficient

Module types are a way to limit what outside code can “see” about the module. Because T.t is abstract, any code outside of module M is only able to see that M.t is abstract as well.

One way to expose the implementation of M.t is to change M: T to M: T with type t = int:

module type T = {
  type t
  let log: t => unit
}

module M: T with type t = int = {
  type t = int
  let log = n => Js.log(n)
}

M.log(1) // This works now.
6 Likes

Ah yes. Thanks, this is great.