caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: "Raphael 'kena' Poss" <r.poss@uva.nl>
To: caml-list@inria.fr
Subject: [Caml-list] Polymorphic module type constraints
Date: Fri, 21 Mar 2014 08:31:22 +0100	[thread overview]
Message-ID: <DC1E40E6-C62A-47BB-9CFF-62B5E45195DB@uva.nl> (raw)

Hi all,

I am trying to take advantage of OCaml locally abstract types to constrain a functor. I want to use this to support the creation of modules from user-provided functions and some defaults. I encounter two issues with polymorphic types, which I am unable to solve. Maybe you will have some suggestions?

To show what I want, here is an example that "works fine" but uses regular types:

  module type Eq = sig
      type t
      val (=) : t -> t -> bool
      val (<>) : t -> t -> bool
    end

  let makeEq (type a) eq =
    let module S  = struct
      type t = a                                                                                                                                              
      let (=) = eq
      let (<>) x y = not (x = y)
    end
    in (module S : Eq with type t = a)

  (* val eq1: int -> int -> bool *)
  let eq1 a b = (a mod 3) = (b mod 3)
  module Eq1 = (val makeEq eq1)

Here, I encounter the first issue:

  (* val eq2: 'a option -> 'a option -> bool *)
  let eq2 a b = match (a, b) with
      | (None, None) -> true
      | (Some x, Some y) -> x = y
      | _ -> false

  module Eq2 = (val makeEq ~eq2)                                                                                                                              

  => 
  Error: The type of this packed module contains variables:
  (module Eq with type t = 'a option)

Is there any way to generalize?



Now, the other issue is when the signature explicitly declares a polymorphic type:

  module type Poly = sig
    type 'a t
  end
  module type Mappable = sig
    type 'a t                                                                                                                                              
    val map : ('a -> 'b) -> 'a t -> 'b t
  end

So far so good; but how to define makeMappable function, that takes a map function and Poly module and defines a Mappable instance from them?

My first try:

  let makeMappable1 (type s) (module O : Poly with type t = s) map =
    let module S : Mappable with type 'a t = 'a O.t = struct
       include O
       let map : ('a -> 'b) -> 'a t -> 'b t = map
    end
    in (module S)

  => 
  Error: In this `with' constraint, the new definition of t
       does not match its original definition in the constrained signature:
       Type declarations do not match: type t is not included in type 'a t

Ok, fair enough:

  let makeMappable2 (type s) (module O : Poly with type 'a t = s) map =
    let module S : Mappable with type 'a t = 'a O.t = ...

  =>
  Error: Syntax error: module-expr expected. (location: with type ... on first line)

So, I try to fix this with:

  let makeMappable3 (module O : Poly) map =
    let module S : Mappable with type 'a t = 'a O.t = struct
       include O
       let map : ('a -> 'b) -> 'a t -> 'b t = map
    end
    in (module S)                                                                                                                                          

  =>
  Error: This expression has type ('a -> 'b) -> 'a O.t -> 'b t
       but an expression was expected of type ('a -> 'b) -> 'a O.t -> 'b t
       The type constructor O.t would escape its scope

Any suggestion as to how to define makeMappable?

Thanks in advance,


-- 
Raphael 'kena' Poss · r.poss@uva.nl
http://staff.science.uva.nl/~poss/








             reply	other threads:[~2014-03-21  7:31 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-21  7:31 Raphael 'kena' Poss [this message]
2014-04-03 16:52 ` Leo White

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DC1E40E6-C62A-47BB-9CFF-62B5E45195DB@uva.nl \
    --to=r.poss@uva.nl \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).