1

I was here for something else but trying to write up my question, I realize there's no way I'm doing this right. I've been using mirage and irmin for a little while, and as long as all the code stays in the Main module everything is great. But of course, it quickly becomes a ridiculously huge file, and trying to split it in modules drives me mad with types escaping their scopes and whatnot.

Instead of just passing console from start to some other functions, I have to put those other functions in a functor that will take the Mirage_types_lwt.CONSOLE as well as the actual console variable, which means everything ends up being in functors instantiated from start and passed around in an unreadable mess of code.

I'm having problems making a giant ugly module to store and pass all of this easily (to "isolate" the parts that need this mess from regular code), and I can't figure out how to declare something like this :

module type ContextConfig = sig
  module Store
  val clientctx : Client.ctx
  ....
end

let mkContextConfig (module Store : Repo) ctx =
  (module struct
    (module Store : Repo)
    let clientctx = ctx
  end : ContextConfig)

(Repo being a module I made to wrap around Irmin's functors). This obviously doesn't work, and I tried so many syntaxes I'm guessing it's just not possible, that means I'm doing something very wrong ?

I'd love advice on the proper way to deal with all of those functors and types in a clean way, how do I pass around things like the console or a conduit without having to functorize and instantiate everything in the Main module just to pass it around after ?

Ulrar
  • 895
  • 8
  • 17

1 Answers1

5

Definitions like that are possible:

module type REPO = sig end

module type CONTEXT_CONFIG = sig
  module Store : REPO
  val client_ctx : int
end

let mkContextConfig (module Store : REPO) ctx =
  (module struct
    module Store = Store
    let client_ctx = ctx
  end : CONTEXT_CONFIG)

(With some uninteresting changes to make the code type check.)

gsg
  • 9,167
  • 1
  • 21
  • 23