It's also possible to parametrize over abstract types (though
only those without type parameters) that occur in first-class
module signature:
module type CmdIface = sig
type message
val cmd : message -> int
end
module type NetIface = sig
type init
val net : init -> init
end
module Cmd = struct
type message = int
let cmd v = v+1
end
module Net = struct
type 'a init = { cvt: (module CmdIface with type message =
'a) }
let net (init : int init) =
let cvt = init.cvt in
let (module R) = cvt in
R.cmd 1 (* line 22 with error *)
end
let i = { Net.cvt = (module Cmd) };;
Net.net i;;
Let me first explain what is wrong with your code.
The message type in `Cmdlface` is defined as an abstract type with only one operation `cmd : message -> unit`. The module `Cmd` provides a possible implementation for this abstract type.The `R.cmd 1` expression tries to break the abstraction by assuming that the `R` implementation is using the `int` type as an underlying implementation. Imagine, what will happen if the `Net.cvt` field contained another implementation,for example
module Cmd = structtype message = stringlet cmd = print_endlineend
let i = { Net.cvt = (module Cmd: CmdIface) }Net.net i
This will finally lead to a call `print_endline 1` if the type system won't stop you before.
The solution is either to uncover the abstractions and stick to `int` as a concrete representation of the message abstraction or to extend the message abstraction interface with functions that will allow you to create the messages, e.g.,
module type CmdIface = sigtype messageval of_int : int -> messageval cmd : message -> unitend
On Tue, Nov 28, 2017 at 12:55 PM, Serge Sivkov <ssp.mryau@gmail.com> wrote:
Hello,
is there way to fix the following code:
module type CmdIface = sigtype messageval cmd : message -> unitend
module type NetIface = sigtype initval net : init -> initend
module Cmd = structtype message = intlet cmd v = v+1end
module Net = structtype init = { cvt: (module CmdIface) }
let net init =let cvt = init.cvt inlet module R = (val cvt: CmdIface) inR.cmd 1 (* line 22 with error *)end
let i = { Net.cvt = (module Cmd: CmdIface) }Net.net i
I got error:File "t.ml", line 22, characters 22-23:Error: This expression has type int but an expression was expected of typeR.message
In case I do not use types in function signature code works well:module type I = sig val f : int -> int end;;module M = struct
let f v = v+1
end;;
type t = {cvt: (module M); v: int};;
let module R = (val i.cvt: I) in R.f i.v;;
- : int = 1
WBR, ssp
-- Mikhail Mandrykin Linux Verification Center, ISPRAS web: http://linuxtesting.org e-mail: mandrykin@ispras.ru