From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by sympa.inria.fr (Postfix) with ESMTPS id 5348282355 for ; Tue, 28 Nov 2017 19:20:01 +0100 (CET) Authentication-Results: mail3-smtp-sop.national.inria.fr; spf=None smtp.pra=mandrykin@ispras.ru; spf=Pass smtp.mailfrom=mandrykin@ispras.ru; spf=None smtp.helo=postmaster@smtp.ispras.ru Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of mandrykin@ispras.ru) identity=pra; client-ip=83.149.199.196; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="mandrykin@ispras.ru"; x-sender="mandrykin@ispras.ru"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of mandrykin@ispras.ru designates 83.149.199.196 as permitted sender) identity=mailfrom; client-ip=83.149.199.196; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="mandrykin@ispras.ru"; x-sender="mandrykin@ispras.ru"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@smtp.ispras.ru) identity=helo; client-ip=83.149.199.196; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="mandrykin@ispras.ru"; x-sender="postmaster@smtp.ispras.ru"; x-conformance=sidf_compatible IronPort-PHdr: =?us-ascii?q?9a23=3Aj3pX2Rerf+PjF883sDjZzeCClGMj4u6mDksu8pMi?= =?us-ascii?q?zoh2WeGdxc65ZR7h7PlgxGXEQZ/co6odzbGJ4+a9ASQp2tWojjMrSNR0TRgLiM?= =?us-ascii?q?EbzUQLIfWuLgnFFsPsdDEwB89YVVVorDmROElRH9viNRWJ+iXhpRZbIBj0NBJ0?= =?us-ascii?q?K+LpAcaSyp3vj6Hhs6HUNiRWjTz1TrRuKwu9rQTNrYFCgJVtAqc8xxaPpWFHLa?= =?us-ascii?q?Ae/m5yKl/bpBfi5cCutMp46DwWvugw/tNoXqDzfqB+RrtdWmcIKWcwsejqthnK?= =?us-ascii?q?TA/Hw3IaXn8HkRtOS1zA5Rf2RIbysy3St/FlwiCBe9frG+NnEQ++5rtmHUe7wB?= =?us-ascii?q?wMMCQ0pSSO0pR9?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0CCAQALqB1a/8THlVNdGgEBAQEBAgEBA?= =?us-ascii?q?QEIAQEBAYJKgVhuJ4N/ixSQIYhokBsphRwChUkUAQEBAQEBAQEBAWoogjgFAR4?= =?us-ascii?q?BBYI+AQUjBFIQCQIOCicDAgIhJREGAQwGAgEBF4lvAxmKJ51rgW06JocNDYMmA?= =?us-ascii?q?QEBAQEFAQEBAQEBIoM8hXCDAoJrhUmCYwWKQYhIjwM9h3OIIYR5gnmBGodiEU6?= =?us-ascii?q?Ge40yTYl6NiKBUUwyQIIpCYRPPjaJDIFYAQEB?= X-IPAS-Result: =?us-ascii?q?A0CCAQALqB1a/8THlVNdGgEBAQEBAgEBAQEIAQEBAYJKgVh?= =?us-ascii?q?uJ4N/ixSQIYhokBsphRwChUkUAQEBAQEBAQEBAWoogjgFAR4BBYI+AQUjBFIQC?= =?us-ascii?q?QIOCicDAgIhJREGAQwGAgEBF4lvAxmKJ51rgW06JocNDYMmAQEBAQEFAQEBAQE?= =?us-ascii?q?BIoM8hXCDAoJrhUmCYwWKQYhIjwM9h3OIIYR5gnmBGodiEU6Ge40yTYl6NiKBU?= =?us-ascii?q?UwyQIIpCYRPPjaJDIFYAQEB?= X-IronPort-AV: E=Sophos;i="5.44,468,1505772000"; d="scan'208,217";a="246423260" Received: from bran.ispras.ru (HELO smtp.ispras.ru) ([83.149.199.196]) by mail3-smtp-sop.national.inria.fr with ESMTP; 28 Nov 2017 19:20:00 +0100 Received: from [10.10.2.183] (molnar.intra.ispras.ru [10.10.2.183]) by smtp.ispras.ru (Postfix) with ESMTP id CEDE8203E8; Tue, 28 Nov 2017 21:19:57 +0300 (MSK) To: Ivan Gotovchits , Serge Sivkov Cc: OCaml Mailing List References: From: Mikhail Mandrykin Message-ID: Date: Tue, 28 Nov 2017 21:19:57 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.4.0 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/alternative; boundary="------------42D595A30A14F1BCA669CBB3" Content-Language: en-US Subject: Re: [Caml-list] using module with types as record parameter This is a multi-part message in MIME format. --------------42D595A30A14F1BCA669CBB3 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit 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;; Also there's another type error in the example since types of cmd in the Cmdline module type and Cmd module are incompatible (_ -> unit vs. _ -> int). On 28.11.2017 21:09, Ivan Gotovchits wrote: > 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 = struct >       type message = string >       let cmd = print_endline >     end > >     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 = sig >        type message >        val of_int : int -> message >        val cmd : message -> unit >     end > > > > > > On Tue, Nov 28, 2017 at 12:55 PM, Serge Sivkov > wrote: > > Hello, > > is there way to fix the following code: > > module type CmdIface = sig >         type message >         val cmd : message -> unit > 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 init = { cvt: (module CmdIface) } > >         let net init = >                 let cvt = init.cvt in >                 let module R = (val cvt: CmdIface) in >                 R.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 type >          R.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 --------------42D595A30A14F1BCA669CBB3 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 8bit

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;;

Also there's another type error in the example since types of cmd in the Cmdline module type and Cmd module are incompatible (_ -> unit vs. _ -> int).

On 28.11.2017 21:09, Ivan Gotovchits wrote:
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 = struct  
      type message = string 
      let cmd = print_endline
    end 

    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 = sig 
       type message
       val of_int : int -> message
       val cmd : message -> unit
    end





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 = sig
        type message
        val cmd : message -> unit
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 init = { cvt: (module CmdIface) }

        let net init =
                let cvt = init.cvt in
                let module R = (val cvt: CmdIface) in 
                R.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 type
         R.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
--------------42D595A30A14F1BCA669CBB3--