3

When compiling this program:

module type Inc =
    sig
        type t
        val inc : t -> t
    end

module type Dec = 
    sig
        type t
        val dec : t -> t
    end

module Merger (I : Inc) (D : Dec with type t = I.t) =
    struct
        let merge x = x |> I.inc |> D.dec
    end

module IntInc : Inc = 
    struct
        type t = int
        let inc x = x + 10
    end

module IntDec : Dec = 
    struct 
        type t = int
        let dec x = x - 8
    end

module Combiner = Merger (IntInc) (IntDec)

I get the following error:

File "simple.ml", line 30, characters 35-41:
Error: Signature mismatch:
       Modules do not match:
         sig type t = IntDec.t val dec : t -> t end
       is not included in
         sig type t = IntInc.t val dec : t -> t end
       Type declarations do not match:
         type t = IntDec.t
       is not included in
         type t = IntInc.t
       File "simple.ml", line 13, characters 38-50: Expected declaration
       File "simple.ml", line 9, characters 13-14: Actual declaration

I thought that D : Dec with type t = I.t constraint will ensure that D.t = I.t. Why it is not so?

What is more interesting, when I remove module Combiner = Merger (IntInc) (IntDec) line it compiles without errors.

My question is : What am I doing wrong?

KCH
  • 2,794
  • 2
  • 23
  • 22

1 Answers1

6

Your definition of Merger with the constraint is perfectly correct, which is why that part compiles without error.

As you said, the only part that doesn't compile is module Combiner = Merger (IntInc) (IntDec). This is because, as far as OCaml knows, the constraint IntInt.t = IntDec.t is not met. The reason for that is that OCaml does not know that IntInt.t and IntDec.t are int. All it knows is that IntInt : Inc and IntDec : Dec - everything else is a private detail of the module.

To fix this problem you can change the module's headers to IntInt : (Inc with type t = int) and IntDec : (Dec with type t = int), making the type t a part of the modules' public interface rather than a private detail, allowing OCaml to use that information when resolving the constraint of the Merger functor.

sepp2k
  • 363,768
  • 54
  • 674
  • 675