From: Rabih CHAAR <rabih.chaar@lyxor.com>
To: Thomas Braibant <thomas.braibant@gmail.com>
Cc: caml-list@yquem.inria.fr, caml-list-bounces@yquem.inria.fr
Subject: Re: [Caml-list] Phantom types [NC]
Date: Mon, 17 May 2010 17:14:17 +0200 [thread overview]
Message-ID: <OF9A537A71.F8B74C48-ONC1257726.00537D6A-C1257726.0053B4C5@fr.world.socgen> (raw)
In-Reply-To: <AANLkTilqG13QE_3iAcxHXMD99aBZk6HYceKkfN0W2EVT@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 9486 bytes --]
if you define the intermediate type
type s= {l:float}
followed by
type 'a t = 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 <thomas.braibant@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.
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 = float
let x : p1 t = 0.0
let id : p2 t -> p2 t = fun x -> x
let _ = id x (* type checks with type p2 t*)
type 'a t = {l: float}
let x : p1 t = {l = 0.0}
let id : p2 t -> p2 t = fun x -> x
let _ = id x (* ill typed *)
Any thoughts ?
thomas
2010/5/1 Stéphane 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 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 = {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 = {lin = Vec.origin; ang = Vec.origin }
>
> let double_force (v : force kinematic) : force kinematic = {lin =
> Vec.mult 2. v.lin; ang = 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 = ...
>
> 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éphane L.
>
> On Sat, May 1, 2010 at 6:04 PM, Anthony Tavener
> <anthony.tavener@gmail.com> wrote:
>> I have this:
>>
>> type kinematic = { 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
expected, 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 = { r: Vec.t; theta: Vec.t }
>> type acceleration = { a: Vec.t; alpha: Vec.t }
>> type force = { 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, such
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 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
>> 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 to
do
>> this?
>>
>> module type KINEMATIC = 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. as
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 developers
>> 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-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, intended solely for the addressee(s), and may contain legally privileged information.
Any unauthorised use or dissemination is prohibited. E-mails are susceptible 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 confidentiels 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 titre de ce message s'il a ete altere, deforme ou falsifie.
*************************************************************************
[-- Attachment #2: Type: text/html, Size: 12177 bytes --]
next prev parent reply other threads:[~2010-05-17 15:14 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-17 14:59 Phantom types Thomas Braibant
2010-05-17 15:14 ` Rabih CHAAR [this message]
2010-05-17 15:19 ` [Caml-list] Phantom types [NC] Philippe Veber
2010-05-17 16:00 ` Phantom types Dawid Toton
2010-05-17 16:37 ` [Caml-list] " Goswin von Brederlow
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=OF9A537A71.F8B74C48-ONC1257726.00537D6A-C1257726.0053B4C5@fr.world.socgen \
--to=rabih.chaar@lyxor.com \
--cc=caml-list-bounces@yquem.inria.fr \
--cc=caml-list@yquem.inria.fr \
--cc=thomas.braibant@gmail.com \
/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).