OK so just to clarify, the functor method you suggested does the opposite of what I was looking for: if my original module (which I wrote to match an interface) has no 'default function', it adds it, but if my original module provided that function, it's overridden. What I'm looking for is a solution whereby if my original module is missing an interface function, that function is added, but if it already contains a function, the original function takes precedence.

More specifically regarding my example (just to illustrate the idea): the Monad module will be used by other functors to do things, so the Monad interface must define the full interface, including >>.




On Wed, Feb 5, 2014 at 2:43 PM, Martin Jambon <martin.jambon@ens-lyon.org> wrote:
On Wed 05 Feb 2014 10:49:29 AM PST, Yotam Barnoy wrote:
Hello List

I would like the following feature, and I'm not enough of an expert in
module-fu to know if something like this is doable.

Suppose I have a module signature of

module type Monad = sig
  type 'a m
  val return : 'a -> 'a m
  val (>>=) : 'a m -> ('a -> 'b m) -> 'b m
  val (>>) : 'a m -> 'b m -> 'b m
end

I would like to have a default implementation for (>>), since a simple
default implementation is

let (>>) m f = m >>= fun _ -> f

Alternatively, I would like to include this from some DefaultMonad
module, but have the (>>=) referred to in the function be my newly
defined (>>=) implementation (ie. late binding). Is there currently
any way to do this? If not, would there be a way to implement a
partial default implementation built into or associated with a module
signature? Something like

OCaml has functors but they don't support optional fields in their arguments.

You can create a functor Monad.Make that takes a module without (>>) and creates a module with an extra (>>) field. However, if the input module contains (>>) already, the new implementation will override it as in this minimal example:

# module A = struct end;;
module A : sig  end

# module M(A: module type of A) = struct include A let x = 0 end;;
module M : functor (A : sig  end) -> sig val x : int end

# module B = M(struct end);;
module B : sig val x : int end

# module C = M(struct let x = 1 end);;
module C : sig val x : int end

# C.x;;
- : int = 0

C.x is 0, not 1.


There may be clever tricks to support some kind of optional module field pattern, though. I'll let others scratch their heads. :-)



module type Monad = sig... default struct... end

Haskell has this available as part of the semantics of their typeclass
system, and I think it would be really handy to have (if there isn't
already a way to do it currently).

-Yotam