njb
njb

Reputation: 93

Tying up record types between implementations

I'm stuck on how to implement this correctly. I have one file, Mytypes.ml, which contains the signature of a local and remote type which contain the keys for the cipher type - a record containing functions for signing and validating. I have two other files Cipher1.ml and Cipher2.ml

module Mytypes = struct
            type local_t
            type remote_t
            type cipher_t = {
                local_create : unit -> local_t;
                local_sign : local_t -> Cstruct.t -> Cstruct.t;
                remote_create : Cstruct.t -> remote_t;
                remote_validate : remote_t -> Cstruct.t -> bool;
            }
            type key_sets = {
                mutable locals : local_t list;
                mutable remotes : remote_t list;
                mutable ciphers : cipher_t list;
            }
        end

        module Cipher1 = struct
            open Mytypes
            type local_t = {
                secretkey : Cstruct.t;
            }
            type remote_t = {
                publickey : Cstruct.t;
            }
            let c1_local_create () = {secretkey = Cstruct.create 321}
            let c1_local_sign local data () = Cstruct.create 21
            let c1_remote_create public_key_data = {publickey = Cstruct.create 123}
            let c1_remote_validate remote data = true
            let create () = {
                local_create = c1_local_create;
                local_sign   = c1_local_sign;
                remote_create = c1_remote_create;
                remote_validate = c1_remote_validate;
            }
        end

        module Cipher2 = struct
            open Mytypes

            type local_t = {
                ekey1 : Cstruct.t;
            }
            type remote_t = {
                ekey2 : Cstruct.t;
            }
            let c2_local_create () = {ekey1 = Cstruct.create 321}
            let c2_local_sign local data () = Cstruct.create 12
            let c2_remote_create public_key_data = {ekey1 = Cstruct.create 123}
            let c2_remote_validate remote data = true
            let create () = {
                local_create = c2_local_create;
                local_sign   = c2_local_sign;
                remote_create = c2_remote_create;
                remote_validate = c2_remote_validate;
            }
        end

The error I always get is:

File "cipher1.ml", line 14, characters 19-34:
        Error: This expression has type unit -> local_t
               but an expression was expected of type unit -> Mytypes.local_t
               Type local_t is not compatible with type Mytypes.local_t 
        ocamlmklib returned with exit code 2

Can anyone suggest a possible way forward?

Upvotes: 2

Views: 59

Answers (1)

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66803

It's not completely clear, but I'll assume that your example code represents three files named mytypes.ml, cipher1.ml and cipher2.ml.

The first thing to notice is that when you say open Mtypes, you're making available the top-level names of the file mtypes.ml. But there's only one top-level name in that file, Mytypes.

OCaml gives you a module for free at the outermost level of a file, so it's fairly rare to have a file containing just one module. This is true for cipher1.ml and cipher2.ml also.

The next thing to notice is that your Mytypes module is declaring local_t and remote_t as abstract types. Since you have no functions returning values of these types, there's no way for another module to create values of these types.

It's certainly not the case that other modules can declare their own versions of the types local_t and remote_t that they want to use.

From the way you've written your code, it's possible you want the definitions in Mytypes to be a module type rather than a module. You can declare a module type like this:

module type Mytypes = sig ... end

Then you can say that other modules have this type:

module cipher1 : Mytypes = struct ... end

Upvotes: 1

Related Questions