From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by yquem.inria.fr (Postfix) with ESMTP id 48508BBAF; Mon, 17 May 2010 17:19:43 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Av8DAE378EvRVaC0imdsb2JhbACRQowoCBUBAQETDBgirW8BBY4FAQSFEA X-IronPort-AV: E=Sophos;i="4.53,247,1272837600"; d="scan'208,217";a="51311834" Received: from mail-gy0-f180.google.com ([209.85.160.180]) by mail2-smtp-roc.national.inria.fr with ESMTP; 17 May 2010 17:19:42 +0200 Received: by gyb13 with SMTP id 13so2088684gyb.39 for ; Mon, 17 May 2010 08:19:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:mime-version:received:in-reply-to :references:from:date:message-id:subject:to:cc:content-type; bh=uNGl/dn7IlrHufJIsSIo8bJhVzgYZauVReS0UMGucoY=; b=Anz2l4yYNGZ+YhXf31J5cz+K1OcX+HXCeEeZNSSPY8bfGTy3AzyqwPim7RLyvPeYkn 9nx1h2CEBDHGYGxA/pP0zwn50kKbWp/F4FsGeIH8yFbwHYMhDWCMdzUGZA6CqRlnlbxv SC+EuwdsZ1INlQZIwOdn83+NiX+i70EZzm57c= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; b=eje2mqFs+G83lCDbZl1jX3Zzi8+NZ1eBU/ibLnhcyNAgmKfFzSdsfIimmRN8iuYEQ5 UbgWF+LByAMz7uFLnI/YNubm0zL8ov5t+4vk+vz/ztDO7+vKBnEgi6M4592bBYHH7N0D dF/NpB20EJoK3iYC+9M9ldkzGfzENHgyG0v7c= Received: by 10.231.169.131 with SMTP id z3mr347705iby.48.1274109560362; Mon, 17 May 2010 08:19:20 -0700 (PDT) MIME-Version: 1.0 Received: by 10.231.119.163 with HTTP; Mon, 17 May 2010 08:19:00 -0700 (PDT) In-Reply-To: References: From: Philippe Veber Date: Mon, 17 May 2010 17:19:00 +0200 Message-ID: Subject: Re: [Caml-list] Phantom types [NC] To: Rabih CHAAR Cc: Thomas Braibant , caml-list@yquem.inria.fr, caml-list-bounces@yquem.inria.fr Content-Type: multipart/alternative; boundary=0016e6d27238c017930486cbbf2d X-Spam: no; 0.00; typecheck:01 abbreviation:01 subtyping:01 acceleration:01 annotations:01 mult:01 multiplying:01 explicitely:01 annotations:01 constructors:01 runtime:01 acceleration:01 structurally:01 ocaml:01 subtypes:01 --0016e6d27238c017930486cbbf2d Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable It seems that the expressions typecheck when t is a type abbreviation and not a type definition. I don't know about the actual typing rules but this would be reasonable, I guess. Philippe. 2010/5/17 Rabih CHAAR > > if you define the intermediate type > type s=3D {l:float} > followed by > type 'a t =3D s > everything goes well > > I am unable to give you an explanation about this (the need of the > intermediay type s). I hope someone can shed some light on this. > > Sincerely > > > > *Thomas Braibant * > Sent by: caml-list-bounces@yquem.inria.fr > > 17/05/10 04:59 PM > To > caml-list@yquem.inria.fr > cc > Subject > [Caml-list] Phantom types > > > > > Hi list, > > Following on the thread "Subtyping structurally-equivalent records, or > something like it?", I made some experimentations with phantom types. > Unfortunately, I turns out that I do not understand the results I got. > > Could someone on the list explain why the first piece of code is well > typed, while the second one is not ? > > > type p1 > type p2 > > type 'a t =3D float > let x : p1 t =3D 0.0 > let id : p2 t -> p2 t =3D fun x -> x > let _ =3D id x (* type checks with type p2 t*) > > type 'a t =3D {l: float} > let x : p1 t =3D {l =3D 0.0} > let id : p2 t -> p2 t =3D fun x -> x > let _ =3D id x (* ill typed *) > > Any thoughts ? > > thomas > > > > 2010/5/1 St=E9phane Lescuyer : > > Hi Anthony, > > I think that maybe using phantom types could do the trick : consider > > defining empty types for all the different "kinds" of similar > > constructs that you have, and then define the kinematic record with a > > phantom parameter type. > > > > type position > > type acceleration > > type force > > > > type 'a kinematic =3D {lin : Vec.t; ang: Vec.t} > > > > By adding some extra typing annotations, you can then constraint your > > functions to accept (or produce) only a given kind of construct, say > > for example a position kinematic : > > > > let pos_0 : position kinematic =3D {lin =3D Vec.origin; ang =3D Vec.ori= gin } > > > > let double_force (v : force kinematic) : force kinematic =3D {lin =3D > > Vec.mult 2. v.lin; ang =3D v.ang } > > > > double_force pos_0 -> does not type check > > > > You can write generic functions as add, norm, products, etc : they are > > just polymorphic with respect to the phantom type parameter. By the > > way you ensure that you are not multiplying apples and carrots : > > let plus (v : 'a kinematic) (v' : 'a kinematic) : 'a kinematic =3D ... > > > > Of course, the overhead is that you have to explicitely write some > > type annotations, especially for constructors, but the runtime > > overhead is exactly 0. And also, one limitation is that you can't use > > different projection names for the different cosntructs, since it is > > really always the same record type that you are using. > > > > I hope this helps, > > > > St=E9phane L. > > > > On Sat, May 1, 2010 at 6:04 PM, Anthony Tavener > > wrote: > >> I have this: > >> > >> type kinematic =3D { lin: Vec.t; ang: Vec.t } > >> > >> Which I've been using to represent a medley of physical attributes > (force, > >> momentum, velocity, etc.). > >> > >> As the physics code becomes increasingly substantial I'm running into > >> possible human-error, like passing a momentum where a force is expecte= d, > or > >> a mass instead of inverse-mass (mass is also a record though different= , > but > >> inv-mass has the same structure as mass). So I'd like to make distinct > >> types, such as: > >> > >> type position =3D { r: Vec.t; theta: Vec.t } > >> type acceleration =3D { a: Vec.t; alpha: Vec.t } > >> type force =3D { f: Vec.t; tau: Vec.t } > >> > >> They are structurally equivalent, and ideally I'd like to be able to > treat > >> these as 'kinematic' too, since that is how I would express the > arithmetic > >> and common functions on these types (add, mul, etc). > >> > >> > >> I'm sure I've seen posts on this before but I can't find them now > (though > >> what I remember are questions about having distinct 'float' types, suc= h > as > >> for degrees vs radians, rather than records). > >> > >> I know OCaml doesn't have subtypes for records, which is effectively > what > >> I'm looking for. Though this case is a bit more specialized that that.= .. > all > >> the subtypes and base type are structurally equivalent. Code for one o= f > >> these types would technically work on any... but is there a way to > inform > >> the type system of my intentions? > >> > >> > >> I hope someone has a better option than those I've considered, or that= I > >> have a grave misunderstanding somewhere and one of these options is > actually > >> good: > >> > >> 1. Objects. Subtyping makes these a natural fit, but in this case I > don't > >> need anything else which objects provide, and a certainly don't need t= he > >> poor performance or method-calling mixed in with my computational code > >> (aesthetically... yucky, to me). Again, each type is structurally > >> equivalent. Just some functions want certain types. > >> > >> 2. Using distinct records for each type, but no 'kinematic' base type, > so > >> all common operations are duplicated for each new type. No performance > hit. > >> But the redundant code is horrible -- makes extensions a pain, and a > >> potential bug-source. > >> > >> 2b. Same as above, but putting the common code in a functor which we > apply > >> on all the different types. I think this will add some overhead, since > the > >> signature of the types (below) would demand accessor functions for the > >> record fields, in order to uniformly get the fields from the different > types > >> (again, even though they are structurally equivalent) -- these calls > >> probably wouldn't get optimized out. But maybe there is a better way t= o > do > >> this? > >> > >> module type KINEMATIC =3D sig > >> type t > >> val lin : t -> Vec.t > >> val ang : t -> Vec.t > >> end > >> > >> 3. Making all the other types different aliases of 'kinematic'; then > using > >> explicit type declarations in function parameters and coercion to > >> 'kinematic' when needed. This makes some ugly code, and the > added-typesafety > >> is almost illusory. This is kind-of like 'typesafe' C code doing > typecasting > >> gymnastics. > >> > >> 4. Adapter functions: 'kinematic_of_force: force -> kinematic', etc. a= s > a > >> way to use the common set of 'kinematic' functions. This is clunky and > comes > >> with a big performance hit unless these functions became like > >> type-coercions. If there is a way this can be done with zero runtime > cost, > >> I'd accept the clunkiness. :) > >> > >> Any thoughts? > >> > >> > >> I've been using OCaml for a few years now, but this is my first post. = I > feel > >> many of you are familiar online personae through reading archives, > blogs, > >> and websites. Thank-you for all the help I've absorbed through those > various > >> channels. And thanks to those making the language I favor for most > tasks! > >> > >> Briefly introducing myself: I've been a professional video-game > developer > >> for 15 years, most recently specializing in AI. I quit my last job > almost > >> two years ago to travel and program (95% in OCaml!), and am developing= a > >> game now. I've seen indications over the years of other game developer= s > >> taking the plunge and then parting ways with OCaml, surely back to C++= . > I > >> see OCaml as viable and certainly more pleasurable, even with avoiding > >> mutation. But within a pressure-cooker environment (working for $$ fro= m > >> someone else) people fall back on what they are most familiar with... > also > >> you can't go too rogue while still being part of a team. :) > >> > >> -Anthony Tavener > >> > >> _______________________________________________ > >> Caml-list mailing list. Subscription management: > >> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > >> Archives: http://caml.inria.fr > >> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > >> Bug reports: http://caml.inria.fr/bin/caml-bugs > >> > >> > > > > > > > > -- > > I'm the kind of guy that until it happens, I won't worry about it. - > > R.H. RoY05, MVP06 > > > > _______________________________________________ > > Caml-list mailing list. Subscription management: > > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > > Archives: http://caml.inria.fr > > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > > Bug reports: http://caml.inria.fr/bin/caml-bugs > > > > _______________________________________________ > Caml-list mailing list. Subscription management: > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > Archives: http://caml.inria.fr > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > > ************************************************************************* > This message and any attachments (the "message") are confidential, intend= ed solely for the addressee(s), and may contain legally privileged informat= ion. > Any unauthorised use or dissemination is prohibited. E-mails are suscepti= ble to alteration. > Neither SOCIETE GENERALE nor any of its subsidiaries or affiliates shall = be liable for the message if altered, changed or > falsified. > ************ > Ce message et toutes les pieces jointes (ci-apres le "message") sont conf= identiels et susceptibles de contenir des informations couvertes > par le secret professionnel. > Ce message est etabli a l'intention exclusive de ses destinataires. Toute= utilisation ou diffusion non autorisee est interdite. > Tout message electronique est susceptible d'alteration. > La SOCIETE GENERALE et ses filiales declinent toute responsabilite au tit= re de ce message s'il a ete altere, deforme ou falsifie. > ************************************************************************* > > > _______________________________________________ > Caml-list mailing list. Subscription management: > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > Archives: http://caml.inria.fr > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > > --0016e6d27238c017930486cbbf2d Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable It seems that the expressions typecheck when t is a type abbreviation and n= ot a type definition. I don't know about the actual typing rules but th= is would be reasonable, I guess.

Philippe.

2010/5/17 Rabih CHAAR <rabih.chaar@lyxor.com>

if you define the intermediate typ= e
type s=3D {l:float}
followed by
type 'a t =3D s
everything goes well

I am unable to give you an explana= tion about this (the need of the intermediay type s). I hope someone can shed some light on this.

Sincerely



Tho= mas Braibant <thomas.b= raibant@gmail.com>
Sent by: caml-list-bounces@yquem.inria.= fr

17/05/10 04:59 PM

To
caml-list@yquem.inria.fr
cc
Subject
[Caml-list] Phantom types





Hi list,

Following on the thread "Subtyping structurally-equivalent records, or
something like it?", I made some experimentations with phantom types.<= br> Unfortunately, I turns out that I do not understand the results I got.

Could someone on the list explain why the first piece of code is well
typed, while the second one is not ?


type p1
type p2

type 'a t =3D float
let x : p1 t =3D 0.0
let id : p2 t -> p2 t =3D fun x -> x
let _ =3D id x (* type checks with type p2 t*)

type 'a t =3D {l: float}
let x : p1 t =3D {l =3D 0.0}
let id : p2 t -> p2 t =3D fun x -> x
let _ =3D id x (* ill typed *)

Any thoughts ?

thomas



2010/5/1 St=E9phane Lescuyer <stephane.lescuyer@inria.fr>:
> Hi Anthony,
> I think that maybe using phantom types could do the trick : consider > defining empty types for all the different "kinds" of simila= r
> constructs that you have, and then define the kinematic record with a
> phantom parameter type.
>
> type position
> type acceleration
> type force
>
> type 'a kinematic =3D {lin : Vec.t; ang: Vec.t}
>
> By adding some extra typing annotations, you can then constraint your<= br> > functions to accept (or produce) only a given kind of construct, say > for example a position kinematic :
>
> let pos_0 : position kinematic =3D {lin =3D Vec.origin; ang =3D Vec.or= igin }
>
> let double_force (v : force kinematic) : force kinematic =3D {lin =3D<= br> > Vec.mult 2. v.lin; ang =3D v.ang }
>
> double_force pos_0 -> does not type check
>
> You can write generic functions as add, norm, products, etc : they are
> just polymorphic with respect to the phantom type parameter. By the > way you ensure that you are not multiplying apples and carrots :
> let plus (v : 'a kinematic) (v' : 'a kinematic) : 'a k= inematic =3D ...
>
> Of course, the overhead is that you have to explicitely write some
> type annotations, especially for constructors, but the runtime
> overhead is exactly 0. And also, one limitation is that you can't use
> different projection names for the different cosntructs, since it is
> really always the same record type that you are using.
>
> I hope this helps,
>
> St=E9phane L.
>
> On Sat, May 1, 2010 at 6:04 PM, Anthony Tavener
> <ant= hony.tavener@gmail.com> wrote:
>> I have this:
>>
>> =A0 type kinematic =3D { lin: Vec.t; ang: Vec.t }
>>
>> Which I've been using to represent a medley of physical attrib= utes (force,
>> momentum, velocity, etc.).
>>
>> As the physics code becomes increasingly substantial I'm runni= ng into
>> possible human-error, like passing a momentum where a force is expected, or
>> a mass instead of inverse-mass (mass is also a record though diffe= rent, but
>> inv-mass has the same structure as mass). So I'd like to make distinct
>> types, such as:
>>
>> =A0 type position =3D { r: Vec.t; theta: Vec.t }
>> =A0 type acceleration =3D { a: Vec.t; alpha: Vec.t }
>> =A0 type force =3D { f: Vec.t; tau: Vec.t }
>>
>> They are structurally equivalent, and ideally I'd like to be a= ble to treat
>> these as 'kinematic' too, since that is how I would expres= s the arithmetic
>> and common functions on these types (add, mul, etc).
>>
>>
>> I'm sure I've seen posts on this before but I can't fi= nd them now (though
>> what I remember are questions about having distinct 'float'= ; types, such as
>> for degrees vs radians, rather than records).
>>
>> I know OCaml doesn't have subtypes for records, which is effec= tively what
>> I'm looking for. Though this case is a bit more specialized th= at that... all
>> the subtypes and base type are structurally equivalent. Code for one of
>> these types would technically work on any... but is there a way to inform
>> the type system of my intentions?
>>
>>
>> I hope someone has a better option than those I've considered, or that I
>> have a grave misunderstanding somewhere and one of these options is actually
>> good:
>>
>> 1. Objects. Subtyping makes these a natural fit, but in this case I don't
>> need anything else which objects provide, and a certainly don'= t need the
>> poor performance or method-calling mixed in with my computational code
>> (aesthetically... yucky, to me). Again, each type is structurally<= br> >> equivalent. Just some functions want certain types.
>>
>> 2. Using distinct records for each type, but no 'kinematic'= ; base type, so
>> all common operations are duplicated for each new type. No perform= ance hit.
>> But the redundant code is horrible -- makes extensions a pain, and a
>> potential bug-source.
>>
>> 2b. Same as above, but putting the common code in a functor which we apply
>> on all the different types. I think this will add some overhead, since the
>> signature of the types (below) would demand accessor functions for the
>> record fields, in order to uniformly get the fields from the diffe= rent types
>> (again, even though they are structurally equivalent) -- these calls
>> probably wouldn't get optimized out. But maybe there is a bett= er way to do
>> this?
>>
>> =A0 module type KINEMATIC =3D sig
>> =A0=A0=A0 type t
>> =A0=A0=A0 val lin : t -> Vec.t
>> =A0=A0=A0 val ang : t -> Vec.t
>> =A0 end
>>
>> 3. Making all the other types different aliases of 'kinematic&= #39;; then using
>> explicit type declarations in function parameters and coercion to
>> 'kinematic' when needed. This makes some ugly code, and th= e added-typesafety
>> is almost illusory. This is kind-of like 'typesafe' C code= doing typecasting
>> gymnastics.
>>
>> 4. Adapter functions: 'kinematic_of_force: force -> kinemat= ic', etc. as a
>> way to use the common set of 'kinematic' functions. This i= s clunky and comes
>> with a big performance hit unless these functions became like
>> type-coercions. If there is a way this can be done with zero runti= me cost,
>> I'd accept the clunkiness. :)
>>
>> Any thoughts?
>>
>>
>> I've been using OCaml for a few years now, but this is my firs= t post. I feel
>> many of you are familiar online personae through reading archives, blogs,
>> and websites. Thank-you for all the help I've absorbed through those various
>> channels. And thanks to those making the language I favor for most tasks!
>>
>> Briefly introducing myself: I've been a professional video-gam= e developer
>> for 15 years, most recently specializing in AI. I quit my last job almost
>> two years ago to travel and program (95% in OCaml!), and am develo= ping a
>> game now. I've seen indications over the years of other game d= evelopers
>> taking the plunge and then parting ways with OCaml, surely back to C++. I
>> see OCaml as viable and certainly more pleasurable, even with avoiding
>> mutation. But within a pressure-cooker environment (working for $$ from
>> someone else) people fall back on what they are most familiar with... also
>> you can't go too rogue while still being part of a team. :) >>
>> -Anthony Tavener
>>
>> _______________________________________________
>> Caml-list mailing list. Subscription management:
>> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-li= st
>> Archives: http:= //caml.inria.fr
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginner= s
>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>>
>>
>
>
>
> --
> I'm the kind of guy that until it happens, I won't worry about= it. -
> R.H. RoY05, MVP06
>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives:
http://ca= ml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports:
http://caml.inria.fr/bin/caml-bugs
>

_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list Archives: http://caml.in= ria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

******************************************************************=
*******
This message and any attachments (the "message") are confidential=
, intended solely for the addressee(s), and may contain legally privileged =
information.
Any unauthorised use or dissemination is prohibited. E-mails are susceptibl=
e to alteration.  =20
Neither SOCIETE GENERALE nor any of its subsidiaries or affiliates shall be=
 liable for the message if altered, changed or
falsified.
                              ************
Ce message et toutes les pieces jointes (ci-apres le "message") s=
ont confidentiels et susceptibles de contenir des informations couvertes=20
par le secret professionnel.=20
Ce message est etabli a l'intention exclusive de ses destinataires. Tou=
te utilisation ou diffusion non autorisee est interdite.
Tout message electronique est susceptible d'alteration.=20
La SOCIETE GENERALE et ses filiales declinent toute responsabilite au titre=
 de ce message s'il a ete altere, deforme ou falsifie.
*************************************************************************

_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list Archives: http://caml.in= ria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs


--0016e6d27238c017930486cbbf2d--