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 mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by sympa.inria.fr (Postfix) with ESMTPS id C13007F1C9 for ; Sat, 10 Nov 2012 08:49:59 +0100 (CET) Received-SPF: None (mail4-smtp-sop.national.inria.fr: no sender authenticity information available from domain of gabriel.scherer@gmail.com) identity=pra; client-ip=209.85.223.182; receiver=mail4-smtp-sop.national.inria.fr; envelope-from="gabriel.scherer@gmail.com"; x-sender="gabriel.scherer@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail4-smtp-sop.national.inria.fr: domain of gabriel.scherer@gmail.com designates 209.85.223.182 as permitted sender) identity=mailfrom; client-ip=209.85.223.182; receiver=mail4-smtp-sop.national.inria.fr; envelope-from="gabriel.scherer@gmail.com"; x-sender="gabriel.scherer@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail4-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-ie0-f182.google.com) identity=helo; client-ip=209.85.223.182; receiver=mail4-smtp-sop.national.inria.fr; envelope-from="gabriel.scherer@gmail.com"; x-sender="postmaster@mail-ie0-f182.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AuEBANQGnlDRVd+2m2dsb2JhbABEhhmrFpIcCCMBAQEBAQgJCwkUJ4IeAQEFIwQZARsSCwEDDAYFCw0CAgkdAgIhAQERAQUBChIGExKHZQEDDwufKItjT4J4hFUKGScDClmIdQEFDIEWigpohTeBEwOUJoFVgRyKFoMwFimEEoFcJA X-IronPort-AV: E=Sophos;i="4.80,750,1344204000"; d="scan'208";a="161998128" Received: from mail-ie0-f182.google.com ([209.85.223.182]) by mail4-smtp-sop.national.inria.fr with ESMTP/TLS/RC4-SHA; 10 Nov 2012 08:49:58 +0100 Received: by mail-ie0-f182.google.com with SMTP id k10so12214393iea.27 for ; Fri, 09 Nov 2012 23:49:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type:content-transfer-encoding; bh=898kYQ1bbS51n0JTV/Cnx62aDlyQxzmWSV8VWVQqhY0=; b=I2KEscapM2asRBYzPndg9zkk9wY3Jvx0vh6STFKwyxua9L3GeGR6xFrayfAnx2NPEC SxjEgQ6JHo88xtzDdalQtoPZVYHB4Y07dYcsrO/6f4k4sMv6oh59y32jHliQRP6NIlLJ LHhteKsa0xL8ndtq8nmWfg1AZKAuswSVuWmauJSqIsjYXu8Ee5/8adE4XtMzdHlX/RJr OCh1BdlJhtOIZVIucOAqT+Amxvm2ZBL1z51naHK5EDTDVX0tMl51quaryaI9O1nynJz2 +XbyTaJmcrpSUZDy+7VJIGsG4U4IB6qWXpsYSl7uX0mtP0J6TYgz/IeVKtYP29IRcv/3 nqlw== Received: by 10.50.1.170 with SMTP id 10mr2903109ign.2.1352533797515; Fri, 09 Nov 2012 23:49:57 -0800 (PST) MIME-Version: 1.0 Received: by 10.50.184.199 with HTTP; Fri, 9 Nov 2012 23:49:17 -0800 (PST) In-Reply-To: References: From: Gabriel Scherer Date: Sat, 10 Nov 2012 08:49:17 +0100 Message-ID: To: =?ISO-8859-2?Q?Milan_Stanojevi=E6?= Cc: Caml List Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [Caml-list] avoiding boilerplate with phantom types That doesn't directly answer your question, but nowadays with GADTs it is possible to start first from the richly typed declaration (what corresponds to your "phantom type" one, but replaced by real type checks instead of hopeful signature coercion), and define the one without this type information as an existential wrapper on top of it. (* rich statically typed module *) module B =3D struct type 'a t =3D | Unit : unit t | Int : int -> int t | Bool : bool -> bool t let foo : type a . a t -> int option =3D function | Int n -> Some n | _ -> None let bar : type a . a t -> bool option =3D function | Bool b -> Some b | _ -> None let baz n =3D Int n end (* dynamic interface without static type knowledge *) module A =3D struct type a =3D Ex : 'a B.t -> a let foo (Ex b) =3D B.foo b let bar (Ex b) =3D B.bar b let baz n =3D Ex (B.baz n) end If I was to do something like this, I wouldn't directly reproduce the module A with the same interface as B, but rather just wait in the user code for a need to pack or unpack (foo B.t) into a, and do it there -- so A is merely an example of doing that. The upside of this is that it translates your intention without requesting duplication. The downside is that GADT type checks are more complex than just usual algebraic types (with or without phantom types) and the quality of error messages is still pretty experimental. So, not necessarily the right choice right now (but if you're moving into phantom types you're somehow already asking for trouble), but something to think about. On Sat, Nov 10, 2012 at 1:02 AM, Milan Stanojevi=C4=87 = wrote: > This is my use case. > I have a module A with type t and bunch of functions. I want to create > module B which is just a wrapper around A with a phantom type > Roughly > module A : sig > type t > val foo : t -> int > val bar : t -> string > end > > module B : sig > type phantom1 > type phantom2 > type 'a t (* or maybe even type 'a t =3D private A.t *) > val foo : _ t -> int > val bar : _ t -> string > > val validate : phantom1 t -> phantom2 t > end > > I was hoping I can avoid copy-pasting declarations and that I can have > some easy way to have A and B in sync as I add or remove functions > from A. > I was able to do something for implementation B but not for interface. > > B.ml > type this_name_is_not_in_scope =3D A.t > include (A : module type of A with type t =3D this_name_is_not_in_scope) > > type 'a t =3D A.t > type phantom1 > type phantom2 > let validate =3D .... > > But for interface I can't do anything unless I expose type equality > between 'a B.t and A.t (which renders phantom types useless) so I had > to list all the functions by hand. > Does anyone have a better way to do this? > > The problem is that I can't say include module type of A with type t :=3D= 'a t > Why is this disallowed? > > Thanks, > Milan > > -- > 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