caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Referencing a functor type
@ 2016-01-14 11:14 Nick Betteridge
  2016-01-14 11:24 ` Nicolas Ojeda Bar
  0 siblings, 1 reply; 5+ messages in thread
From: Nick Betteridge @ 2016-01-14 11:14 UTC (permalink / raw)
  To: caml-list

Hi,

I'm trying to create a functor for different type of cipher which have
the same signature. The functor compiles Ok, but I can't work out how to
phrase my self_t to build up a list of local key types. Could anyone
suggest a way forward? Thanks, Nick.


module type Cipher = sig

  type local_t
  type remote_t

  val local_create : unit -> local_t
  val local_sign : local_t -> Cstruct.t -> Cstruct.t
  val remote_create : Cstruct.t -> remote_t
  val remote_validate : remote_t -> Cstruct.t -> bool

end

module Make_cipher :

  functor (Cipher_impl : Cipher) ->
    sig
      type local_t = Cipher_impl.local_t
      type remote_t = Cipher_impl.remote_t
      val local_create : unit -> local_t
      val local_sign : local_t -> Cstruct.t -> Cstruct.t
      val remote_create : Cstruct.t -> remote_t
      val remote_validate : remote_t -> Cstruct.t -> bool
    end

type self_t =
  {
    mutable modules : (module Cipher) list;
    mutable locals : Cipher_impl.local_t list;
  }

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Referencing a functor type
  2016-01-14 11:14 [Caml-list] Referencing a functor type Nick Betteridge
@ 2016-01-14 11:24 ` Nicolas Ojeda Bar
  2016-01-18  7:49   ` Nick Betteridge
  0 siblings, 1 reply; 5+ messages in thread
From: Nicolas Ojeda Bar @ 2016-01-14 11:24 UTC (permalink / raw)
  To: Nick Betteridge; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 1566 bytes --]

Hi Nick,

You can wrap the different key types in an existential:

type local_key = LK : 'a * (module Cipher with type local_t = 'a) -> LK

type self_t = local_key list

Cheers,
Nicolas



On Thu, Jan 14, 2016 at 12:14 PM, Nick Betteridge <
lists.nick.betteridge@gmail.com> wrote:

> Hi,
>
> I'm trying to create a functor for different type of cipher which have
> the same signature. The functor compiles Ok, but I can't work out how to
> phrase my self_t to build up a list of local key types. Could anyone
> suggest a way forward? Thanks, Nick.
>
>
> module type Cipher = sig
>
>   type local_t
>   type remote_t
>
>   val local_create : unit -> local_t
>   val local_sign : local_t -> Cstruct.t -> Cstruct.t
>   val remote_create : Cstruct.t -> remote_t
>   val remote_validate : remote_t -> Cstruct.t -> bool
>
> end
>
> module Make_cipher :
>
>   functor (Cipher_impl : Cipher) ->
>     sig
>       type local_t = Cipher_impl.local_t
>       type remote_t = Cipher_impl.remote_t
>       val local_create : unit -> local_t
>       val local_sign : local_t -> Cstruct.t -> Cstruct.t
>       val remote_create : Cstruct.t -> remote_t
>       val remote_validate : remote_t -> Cstruct.t -> bool
>     end
>
> type self_t =
>   {
>     mutable modules : (module Cipher) list;
>     mutable locals : Cipher_impl.local_t list;
>   }
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>

[-- Attachment #2: Type: text/html, Size: 2553 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Referencing a functor type
  2016-01-14 11:24 ` Nicolas Ojeda Bar
@ 2016-01-18  7:49   ` Nick Betteridge
  2016-01-18 14:45     ` Runhang Li
  0 siblings, 1 reply; 5+ messages in thread
From: Nick Betteridge @ 2016-01-18  7:49 UTC (permalink / raw)
  To: Nicolas Ojeda Bar; +Cc: caml-list

Hi Nicolas, everyone,

I'm having problems in reconstituting the variables - I'm pretty sure I
need to do some form of 'casting'. As a recap, I've re-written
everything below with a simple use-case - forming the GADTs works perfectly:


module type Cipher = sig

  type local_t
  type remote_t

  val local_create : unit -> local_t
  val local_sign : local_t -> Cstruct.t -> Cstruct.t
  val remote_create : Cstruct.t -> remote_t
  val remote_validate : remote_t -> Cstruct.t -> bool

end

module Make_cipher :

  functor (Cipher_impl : Cipher) ->
    sig
      type local_t = Cipher_impl.local_t
      type remote_t = Cipher_impl.remote_t
      val local_create : unit -> local_t
      val local_sign : local_t -> Cstruct.t -> Cstruct.t
      val remote_create : Cstruct.t -> remote_t
      val remote_validate : remote_t -> Cstruct.t -> bool
    end

type local_key = LK : 'a * (module Cipher with type local_t = 'a) ->
local_key
type cipher_module = CM : (module Cipher with type local_t = 'a) ->
cipher_module

type self_t =
  {
    mutable modules : cipher_module list;
    mutable locals : local_key list
  }



module C1x = Make_cipher (Cipher1)
module C2x = Make_cipher (Cipher2)

let () =
  let cs1 = ( module C1x : Cipher with type local_t = Cipher1.local_t) in
  let cs2 = ( module C2x : Cipher with type local_t = Cipher2.local_t) in
  let module C1 = (val cs1 : Cipher with type local_t = Cipher1.local_t) in
  let module C2 = (val cs2 : Cipher with type local_t = Cipher2.local_t) in
  let local1 = C1.local_create () in
  let local2 = C2.local_create () in
  let l_k1 = LK (local1, cs1) in
  let l_k2 = LK (local2, cs2) in
  let cm1 = CM (cs1) in
  let cm2 = CM (cs2) in
  let cslist = [cm1;cm2] in
  ignore (C1.local_sign local1 (Cstruct.create 23));
  let self = {
    modules = [cm1;cm2];
    locals = [l_k1;l_k2];
  } in
  let CM cs1' = cm1 in
  let module C1' = (val cs1' : Cipher with type local_t = 'a) in
  let LK (local1', cs1') = l_k1 in
  let signature = C1'.local_sign local1' (Cstruct.create 23) in
  Printf.printf "OK"


An error is given for 'let signature = ....'
Error: This expression has type a#1 but an expression was expected of type
         C1'.local_t = a#0

I've spent quite a while trying to figure this out and playing around
with various permutations and am simply getting nowhere!

Cheers
Nick

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Referencing a functor type
  2016-01-18  7:49   ` Nick Betteridge
@ 2016-01-18 14:45     ` Runhang Li
  2016-01-18 16:02       ` Nick Betteridge
  0 siblings, 1 reply; 5+ messages in thread
From: Runhang Li @ 2016-01-18 14:45 UTC (permalink / raw)
  To: Nick Betteridge; +Cc: Nicolas Ojeda Bar, caml-list

Hi, Nick

Here is my attempt that fixes existential problem. I used heterogeneous list. I am not sure what specific thing you want to do with cipher_module list and local_key list, but feel free to ask me any problem about what you want to do with the list. Also, I used Obj.magic because I don’t know what your implementation about Cipher is, and using Obj.magic does not matter here.

module Cstruct = struct
  type t = string
  let create n = Obj.magic ()
end

module type Cipher = sig

  type local_t
  type remote_t

  val local_create : unit -> local_t
  val local_sign : local_t -> Cstruct.t -> Cstruct.t
  val remote_create : Cstruct.t -> remote_t
  val remote_validate : remote_t -> Cstruct.t -> bool

end

module MMMake_cipher (Cipher_impl : Cipher) = struct
  type local_t = Cipher_impl.local_t
  type remote_t = Cipher_impl.remote_t

  let local_create = Cipher_impl.local_create
  let local_sign = Cipher_impl.local_sign
  let remote_create = Cipher_impl.remote_create
  let remote_validate = Cipher_impl.remote_validate
end


type _ local_key =
    LK : 'a * (module Cipher with type local_t = 'a) -> 'a local_key

type local_key_list =
  | KNil :  local_key_list
  | KCons : 'a local_key * local_key_list -> local_key_list

type _ cipher_module =
    CM : (module Cipher with type local_t = 'a) -> 'a cipher_module

type cipher_module_list =
  | MNil :  cipher_module_list
  | MCons : 'a cipher_module * cipher_module_list -> cipher_module_list

type self_t = {
  mutable modules : cipher_module_list;
  mutable locals : local_key_list
}

module Cipher1 : Cipher = struct
  type local_t
  type remote_t
  let local_create = fun _ -> Obj.magic ()
  let local_sign = fun _ _ -> Obj.magic ()
  let remote_create = fun _ -> Obj.magic ()
  let remote_validate = fun _ _ -> Obj.magic ()
end

module Cipher2 : Cipher = struct
  type local_t
  type remote_t
  let local_create = fun _ -> Obj.magic ()
  let local_sign = fun _ _ -> Obj.magic ()
  let remote_create = fun _ -> Obj.magic ()
  let remote_validate = fun _ _ -> Obj.magic ()
end

module C1x = MMMake_cipher(Cipher1)
module C2x = MMMake_cipher(Cipher2)


let () =
  let cs1 = (module C1x : Cipher with type local_t = Cipher1.local_t) in
  let cs2 = (module C2x : Cipher with type local_t = Cipher2.local_t) in
  let module C1 = (val cs1 : Cipher with type local_t = Cipher1.local_t) in
  let module C2 = (val cs2 : Cipher with type local_t = Cipher2.local_t) in
  let local1 = C1.local_create () in
  let local2 = C2.local_create () in
  let l_k1 = LK (local1, cs1) in
  let l_k2 = LK (local2, cs2) in
  let cm1 = CM (cs1) in
  let cm2 = CM (cs2) in
  ignore (C1.local_sign local1 (Cstruct.create 23));
  let self = {
    modules = MCons (cm1, MCons(cm2, MNil));
    locals = KCons (l_k1, KCons(l_k2, KNil));
  } in
  let CM cs1' = cm1 in
  let module C1' = (val cs1' : Cipher with type local_t = 'a) in
  let LK (local1', cs1') = l_k1 in
  let signature = C1'.local_sign local1' (Cstruct.create 23) in
  Printf.printf "OK"


> On Jan 18, 2016, at 2:49 AM, Nick Betteridge <lists.nick.betteridge@gmail.com> wrote:
> 
> Hi Nicolas, everyone,
> 
> I'm having problems in reconstituting the variables - I'm pretty sure I
> need to do some form of 'casting'. As a recap, I've re-written
> everything below with a simple use-case - forming the GADTs works perfectly:
> 
> 
> module type Cipher = sig
> 
>  type local_t
>  type remote_t
> 
>  val local_create : unit -> local_t
>  val local_sign : local_t -> Cstruct.t -> Cstruct.t
>  val remote_create : Cstruct.t -> remote_t
>  val remote_validate : remote_t -> Cstruct.t -> bool
> 
> end
> 
> module Make_cipher :
> 
>  functor (Cipher_impl : Cipher) ->
>    sig
>      type local_t = Cipher_impl.local_t
>      type remote_t = Cipher_impl.remote_t
>      val local_create : unit -> local_t
>      val local_sign : local_t -> Cstruct.t -> Cstruct.t
>      val remote_create : Cstruct.t -> remote_t
>      val remote_validate : remote_t -> Cstruct.t -> bool
>    end
> 
> type local_key = LK : 'a * (module Cipher with type local_t = 'a) ->
> local_key
> type cipher_module = CM : (module Cipher with type local_t = 'a) ->
> cipher_module
> 
> type self_t =
>  {
>    mutable modules : cipher_module list;
>    mutable locals : local_key list
>  }
> 
> 
> 
> module C1x = Make_cipher (Cipher1)
> module C2x = Make_cipher (Cipher2)
> 
> let () =
>  let cs1 = ( module C1x : Cipher with type local_t = Cipher1.local_t) in
>  let cs2 = ( module C2x : Cipher with type local_t = Cipher2.local_t) in
>  let module C1 = (val cs1 : Cipher with type local_t = Cipher1.local_t) in
>  let module C2 = (val cs2 : Cipher with type local_t = Cipher2.local_t) in
>  let local1 = C1.local_create () in
>  let local2 = C2.local_create () in
>  let l_k1 = LK (local1, cs1) in
>  let l_k2 = LK (local2, cs2) in
>  let cm1 = CM (cs1) in
>  let cm2 = CM (cs2) in
>  let cslist = [cm1;cm2] in
>  ignore (C1.local_sign local1 (Cstruct.create 23));
>  let self = {
>    modules = [cm1;cm2];
>    locals = [l_k1;l_k2];
>  } in
>  let CM cs1' = cm1 in
>  let module C1' = (val cs1' : Cipher with type local_t = 'a) in
>  let LK (local1', cs1') = l_k1 in
>  let signature = C1'.local_sign local1' (Cstruct.create 23) in
>  Printf.printf "OK"
> 
> 
> An error is given for 'let signature = ....'
> Error: This expression has type a#1 but an expression was expected of type
>         C1'.local_t = a#0
> 
> I've spent quite a while trying to figure this out and playing around
> with various permutations and am simply getting nowhere!
> 
> Cheers
> Nick
> 
> -- 
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

Kindly,

Runhang


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Referencing a functor type
  2016-01-18 14:45     ` Runhang Li
@ 2016-01-18 16:02       ` Nick Betteridge
  0 siblings, 0 replies; 5+ messages in thread
From: Nick Betteridge @ 2016-01-18 16:02 UTC (permalink / raw)
  To: Runhang Li; +Cc: Nicolas Ojeda Bar, caml-list

Hi,

Really grateful for help on this and thanks for taking time to write
back. Octachron has just emailed me to suggest swapping two lines to
make sure the type system knows that the existential type local_t inside
cm1 and l_k1 are the same (from my original example) - ie:

  let module C1' = (val cs1' : Cipher with type local_t = 'a) in
  let LK (local1', cs1') = l_k1 in
  let signature = C1'.local_sign local1' (Cstruct.create 23) in

should be

  let LK (local1', cs1') = l_k1 in
  let module C1' = (val cs1' : Cipher with type local_t = 'a) in
  let signature = C1'.local_sign local1' (Cstruct.create 23) in

Your solution, of course :) , also works - what exactly does the '_' do in:

type _ local_key

- am I right in thinking that this was how the type system figured
everything out?

Thanks again for your time,

Cheers
Nick


On 18/01/16 14:45, Runhang Li wrote:
> module Cstruct = struct
>   type t = string
>   let create n = Obj.magic ()
> end
> 
> module type Cipher = sig
> 
>   type local_t
>   type remote_t
> 
>   val local_create : unit -> local_t
>   val local_sign : local_t -> Cstruct.t -> Cstruct.t
>   val remote_create : Cstruct.t -> remote_t
>   val remote_validate : remote_t -> Cstruct.t -> bool
> 
> end
> 
> module MMMake_cipher (Cipher_impl : Cipher) = struct
>   type local_t = Cipher_impl.local_t
>   type remote_t = Cipher_impl.remote_t
> 
>   let local_create = Cipher_impl.local_create
>   let local_sign = Cipher_impl.local_sign
>   let remote_create = Cipher_impl.remote_create
>   let remote_validate = Cipher_impl.remote_validate
> end
> 
> 
> type _ local_key =
>     LK : 'a * (module Cipher with type local_t = 'a) -> 'a local_key
> 
> type local_key_list =
>   | KNil :  local_key_list
>   | KCons : 'a local_key * local_key_list -> local_key_list
> 
> type _ cipher_module =
>     CM : (module Cipher with type local_t = 'a) -> 'a cipher_module
> 
> type cipher_module_list =
>   | MNil :  cipher_module_list
>   | MCons : 'a cipher_module * cipher_module_list -> cipher_module_list
> 
> type self_t = {
>   mutable modules : cipher_module_list;
>   mutable locals : local_key_list
> }
> 
> module Cipher1 : Cipher = struct
>   type local_t
>   type remote_t
>   let local_create = fun _ -> Obj.magic ()
>   let local_sign = fun _ _ -> Obj.magic ()
>   let remote_create = fun _ -> Obj.magic ()
>   let remote_validate = fun _ _ -> Obj.magic ()
> end
> 
> module Cipher2 : Cipher = struct
>   type local_t
>   type remote_t
>   let local_create = fun _ -> Obj.magic ()
>   let local_sign = fun _ _ -> Obj.magic ()
>   let remote_create = fun _ -> Obj.magic ()
>   let remote_validate = fun _ _ -> Obj.magic ()
> end
> 
> module C1x = MMMake_cipher(Cipher1)
> module C2x = MMMake_cipher(Cipher2)
> 
> 
> let () =
>   let cs1 = (module C1x : Cipher with type local_t = Cipher1.local_t) in
>   let cs2 = (module C2x : Cipher with type local_t = Cipher2.local_t) in
>   let module C1 = (val cs1 : Cipher with type local_t = Cipher1.local_t) in
>   let module C2 = (val cs2 : Cipher with type local_t = Cipher2.local_t) in
>   let local1 = C1.local_create () in
>   let local2 = C2.local_create () in
>   let l_k1 = LK (local1, cs1) in
>   let l_k2 = LK (local2, cs2) in
>   let cm1 = CM (cs1) in
>   let cm2 = CM (cs2) in
>   ignore (C1.local_sign local1 (Cstruct.create 23));
>   let self = {
>     modules = MCons (cm1, MCons(cm2, MNil));
>     locals = KCons (l_k1, KCons(l_k2, KNil));
>   } in
>   let CM cs1' = cm1 in
>   let module C1' = (val cs1' : Cipher with type local_t = 'a) in
>   let LK (local1', cs1') = l_k1 in
>   let signature = C1'.local_sign local1' (Cstruct.create 23) in
>   Printf.printf "OK"

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-01-18 16:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-14 11:14 [Caml-list] Referencing a functor type Nick Betteridge
2016-01-14 11:24 ` Nicolas Ojeda Bar
2016-01-18  7:49   ` Nick Betteridge
2016-01-18 14:45     ` Runhang Li
2016-01-18 16:02       ` Nick Betteridge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).