Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why use module type in Ocaml?

I confused with module type in Ocaml.

I wondered that in which situation we should use module type?

I usually use module sig in .mli to expose some detail, and put corresponding implementation module struct in .ml.

For example:

.mli

module A:
 sig
   type t = T of string
 end

.ml

module A =
 struct
   type t = T of string
 end

For this reason, I think Ocaml's module like .h and .c file in C.

I know that module type can declare a interface, but the interface were not as same as Java's interface.

Like an example in book:

open Core.Std

 module type ID = sig
  type t
   val of_string : string -> t
  val to_string : t -> string
 end

  module String_id = struct
   type t = string
    let of_string x = x
    let to_string x = x
  end

  module Username : ID = String_id
  module Hostname : ID = String_id

  type session_info = { user: Username.t;
                  host: Hostname.t;
                  when_started: Time.t;
                }

  let sessions_have_same_user s1 s2 =
       s1.user = s2.host

The preceding code has a bug: it compares the username in one session to the host in the other session, when it should be comparing the usernames in both cases.

It seems that module type can not provide a new common super type for it's implementation.

What the real application for module type??

like image 417
Tiger Avatar asked Jan 04 '23 01:01

Tiger


2 Answers

Here, the module type is used to hide the type t to the user of the module.

When one makes use of Username.t or Hostname.t one can not rely on those types being strings, integers, or any specific type. The module type makes them opaque, as if they were not part of the interface of the module, but only an implementation detail, that the module writer is going to change in the future.

Basically, the user of the module can only act on type t through the module functions.

The compiler checks that the user code does not make any assumptions about what these types t actually are, so that in the future the module writer can change them without breaking the user code.

like image 63
chi Avatar answered Jan 09 '23 04:01

chi


As it already mentioned, here module type is used to achieve more abstract vision of type t. When you define Username and Hostname as two separate modules its means that logically they must be different and that signature of this modules it's the only possible way to work with them.

But you're wrong when you say:

It seems that module type can not provide a new common super type for it's implementation.

Actually you can precise that Username.t and Hostname.t are the same types.

module Username = (String_id : ID with type t = String_id.t)
module Hostname = (String_id : ID with type t = String_id.t)

Username.to_string (Hostname.of_string "hi")

Here it's useless but sometimes it's really helpful.

like image 42
vonaka Avatar answered Jan 09 '23 04:01

vonaka