From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: ** X-Spam-Status: No, score=2.8 required=5.0 tests=DNS_FROM_RFC_POST, HTML_MESSAGE,SPF_NEUTRAL autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail1-relais-roc.national.inria.fr (mail1-relais-roc.national.inria.fr [192.134.164.82]) by yquem.inria.fr (Postfix) with ESMTP id 41F09BC37 for ; Sun, 11 Oct 2009 23:46:11 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AvQEAH/u0UpKfVwaimdsb2JhbACCJS8tjFSKEmc/AQEBCgkMBxEFrAoBBY1VAQaELQ X-IronPort-AV: E=Sophos;i="4.44,543,1249250400"; d="scan'208";a="38026189" Received: from qw-out-2122.google.com ([74.125.92.26]) by mail1-smtp-roc.national.inria.fr with ESMTP; 11 Oct 2009 23:46:09 +0200 Received: by qw-out-2122.google.com with SMTP id 5so1075029qwd.15 for ; Sun, 11 Oct 2009 14:46:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:mime-version:received:in-reply-to:references :date:message-id:subject:from:to:cc:content-type; bh=7bjjmzG7nkmuFsoLY9ME/6goCl76UfKBjXTNgV/xdHg=; b=G2VfKwbM53Zu0qZCDvR18IQjeAkBYw/VT8of7VMDS/HF/CHCGypgcQCwuBGSC7qoYt gWGiP46sfu9pxTgIcERRV+6nCom4VkCZYwY1h+68CIIol9UplG9IFunS8bX6AYdc3YRe hr8LdQP+/b4zdIgy2Rti9hcUDastyxhTfu/uc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; b=iy0bPLyuTxwiICsFbqzazpJs7qQnO8vJ2kI5At/hQ0zSZlIhpLR8FOvY8HhmcWYT07 PTQwksSZxfjWGtt6u7mmamexWOk1qwpzorFeARLFeb15Gy0FucSpWwtRz+8sDu7lrxLH Nnws9Um4G1Ok0dNAKFCWcxY1nDH8hwbP8uSos= MIME-Version: 1.0 Received: by 10.229.15.203 with SMTP id l11mr2187060qca.43.1255297568721; Sun, 11 Oct 2009 14:46:08 -0700 (PDT) In-Reply-To: <200910112317152031791@orange.fr> References: <891bd3390910081840p37e8c786g60b2c15d2c06ae60@mail.gmail.com> <891bd3390910081853m5409c871y35495c6f16e180aa@mail.gmail.com> <5160b4200910110757y47ffad15v70434418cba61f26@mail.gmail.com> <62B782AA-1F44-4207-B037-5C6D1F6CBF50@gmail.com> <5160b4200910110824q7998f43ao3d00e94ba7e74b2b@mail.gmail.com> <605bf2750910111257h1b2b3f31me95be82ba73b65a3@mail.gmail.com> <200910112317152031791@orange.fr> Date: Sun, 11 Oct 2009 14:46:08 -0700 Message-ID: <605bf2750910111446m2d4b91cawf4dbadeed1b6ae88@mail.gmail.com> Subject: Re: [Caml-list] Improving OCaml's choice of type to display From: Gilles Pirio To: Damien Guichard Cc: "caml-list@yquem.inria.fr" Content-Type: multipart/alternative; boundary=0015175ce094abcd380475afbdf5 X-Spam: no; 0.00; ocaml's:01 ocaml:01 damien:01 mismatch:01 ocaml:01 val:01 val:01 damien:01 guichard:01 rewriting:01 typer:01 syntax:01 typer:01 semantically:01 ocaml's:01 --0015175ce094abcd380475afbdf5 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Hey Damien Sure, I fully understand that both types are equivalent given the rules governing the application operator. My point was more on the usability side= , as the type display is primarily intended at helping the programmer to quickly figure out type mismatch. So I'd think having a display allowing to quickly distinguish between the noe and castro functions below would be a good thing, especially for beginners. I've been using ocaml for a few years now, and I have to say that it's not a major issue any more - just wanted t= o give some feedback about this. Thanks Gilles # let noe a b =3D a;; val noe : 'a -> 'b -> 'a =3D # let castro a =3D fun _ -> a;; val castro : 'a -> 'b -> 'a =3D On Sun, Oct 11, 2009 at 2:17 PM, Damien Guichard wrot= e: > > Hi Gilles, > > The type display routine uses right-associativity of the -> operator as a > rewriting rule. > Thus *('a -> 'a -> float)* and *'a -> ('a -> float)* are the same type an= d > are both displayed as *'a -> 'a -> float*. > > The type *'a -> ('a -> float)* means the application will be *(f x) y*whi= ch is actually the same as > *f x y* because the application is left-associative. > The typer system doesn't care about your actual code syntax, and rightly = so > because the typer system is about semantic. > You intend to write *(f x) y,* yet the type system tells you intend to > write *f x y*, that's quite disturbing at first encounter. > > Suffice to say you have to get your head around it. > Mind the right-associativity of -> and the left-associativity of > application. > Think your code more semantically and less syntactically. > In the end this type sytem makes you a better programmer. > > - *damien* > > > ------------------------------ > *En r=E9ponse au message* > *de :* Gilles Pirio > *du :* 2009-10-11 21:57:40 > *=C0 :* caml-list@yquem.inria.fr > *CC :* > *Sujet :* Re: [Caml-list] Re: Improving OCaml's choice of type to display > > > On the same topic, I was wondering why the type of the ampl_scalar_app > function below was displayed as ('a -> 'a -> float) -> 'a -> 'a -> float > rather than ('a -> 'a -> float) -> 'a -> ('a -> float). The latter would > make my life easier. > > # let ampl_scalar_app f p =3D if f p p > 1. then fun x->f x p else fun x-= >f p > x;; > val ampl_scalar_app : ('a -> 'a -> float) -> 'a -> 'a -> float =3D > > PS: I can imagine this has been discussed extensively before, feel free t= o > just send my a link to the relevant discussion if that's the case :) > > Giles > > > On Sun, Oct 11, 2009 at 8:24 AM, Jun Furuse wrote: > >> I have not tested it well but it counts dots and should try to find >> the minimal one. >> >> A problem I have found so far is that it prints something confusing, ex. >> >> module M =3D struct type t end >> module N =3D struct type t end >> open M >> open N >> >> let _ =3D ( 1 : M.t ) >> >> >> Error: This expression has type int but an expression was expected of >> type t (which t ?!?!?) >> >> If there are types M.t and N.t and the both of M and N are opened, >> these types are printed just "t". This can be avoided by testing the >> result name "t" against the current typing envrionment to see it >> really means the original type "M.t". This requires more coding but >> the weekend has ended in the far east already :-) (It's 0:24 Monday >> now.) >> >> Jun >> >> On Mon, Oct 12, 2009 at 12:12 AM, Yaron Minsky wrote= : >> > Cool! That was quick. >> > >> > Does this patch also implement stephen's fewest-number-of-dots >> heuristic? I >> > was thinking one nice approach would be fewest-number-of-dots with tie= s >> > broken by length of final identifier. >> > >> > Y >> > >> > Yaron Minsky >> > >> > On Oct 11, 2009, at 10:57 AM, Jun Furuse wrote: >> > >> >> I have quickly wrote a small patch against 3.11.1 for this feature, t= o >> >> see what it would be like. >> >> >> >> >> http://sites.google.com/a/furuse.info/jun/hacks/other-small-ocaml-patche= s >> >> >> >> With this patch, path names are printed without opened modules in the >> >> context. It also tries heuristic data type name simplification: if a >> >> variant/record data type is an alias of another data type whose name >> >> is shorter than the original, the printer uses the latter. >> >> >> >> For example: >> >> >> >> # open Hashtbl;; >> >> # let tbl =3D Hashtbl.create 10;; >> >> val tbl : ('_a, '_b) t =3D (* not Hashtbl.t, since Hasht= bl >> is >> >> open *) >> >> >> >> # type t =3D int;; >> >> type t =3D int >> >> # type long_name =3D int;; >> >> type long_name =3D int >> >> # (1 : t);; >> >> - : t =3D 1 (* t is the shorter than its original >> type >> >> int *) >> >> # (1 : long_name);; >> >> - : int =3D 1 (* int is shorter name for long_name.= t >> >> is even shorter but not aliased unfortunatelly. *) >> >> >> >> I warn you that the patch is very quickly written and not tested well= . >> >> Enjoy! >> >> >> >> Jun >> >> >> >> On Fri, Oct 9, 2009 at 10:53 AM, Yaron Minsky >> wrote: >> >>> >> >>> And you can compete to come up with the most innocuous code that com= es >> up >> >>> with the longest type. Here's my current favorite: >> >>> >> >>> # open Option.Monad_infix;; >> >>> # Map.find m 3 >>| fun x -> x + 1;; >> >>> - : int Core.Std.Option.Monad_infix.monad =3D Some 4 >> >>> >> >>> Which of course could be rendered as: >> >>> >> >>> # open Option.Monad_infix;; >> >>> # Map.find m 3 >>| fun x -> x + 1;; >> >>> - : int option =3D Some 4 >> >>> >> >>> y >> >>> >> >>> On Thu, Oct 8, 2009 at 9:40 PM, Yaron Minsky >> wrote: >> >>>> >> >>>> Anyone who plays around with the Core library that Jane Street just >> >>>> released can see showcased a rather ugly detail of how Core's desig= n >> >>>> interacts with how OCaml displays types. Witness: >> >>>> >> >>>> # Int.of_string;; >> >>>> - : string -> Core.Std.Int.stringable =3D >> >>>> # Float.of_string;; >> >>>> - : string -> Core_extended.Std.Float.stringable =3D >> >>>> >> >>>> I'd be much happier if this was rendered in the following equally >> >>>> correct >> >>>> and more readable form: >> >>>> >> >>>> # Int.of_string;; >> >>>> - : string -> Int.t =3D >> >>>> # Float.of_string;; >> >>>> - : string -> Float.t =3D >> >>>> >> >>>> Or even: >> >>>> >> >>>> # Int.of_string;; >> >>>> - : string -> int =3D >> >>>> # Float.of_string;; >> >>>> - : string -> float =3D >> >>>> >> >>>> And this isn't just an issue in the top-level. The compiler also >> >>>> displays >> >>>> types in the same difficult to read form. I'm wondering if anyone >> has >> >>>> some >> >>>> thoughts as to what we can do to make the compiler make better >> choices >> >>>> here. There are two issues to overcome: >> >>>> >> >>>> Dropping the module name. I'd love to give the compiler the hint >> that >> >>>> Core.Std. could be dropped from the prefix in a context where that >> >>>> module is >> >>>> open. This is what's done with the pervasives module already, I >> >>>> believe, so >> >>>> it seems like it should be doable here. >> >>>> Choosing shorter names. This one seems harder, but there are vario= us >> >>>> different possibilities for what type name to print out, and a >> >>>> reasonable >> >>>> heuristic to use might be to pick the shortest one. Part of the >> reason >> >>>> these issues come up is our use of standardized interface component= s >> >>>> (that's >> >>>> where the "stringable" type name comes from). I suspect this one >> will >> >>>> be >> >>>> hard to fix, sadly. >> >>>> >> >>>> Anyway, we'd be happy with any suggestions on how to improve matter= s. >> >>>> >> >>>> y >> >>> >> >>> >> >>> _______________________________________________ >> >>> 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 >> > > > _______________________________________________ > 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 > > --0015175ce094abcd380475afbdf5 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Hey Damien

Sure, I fully understand that both types are equivalent g= iven the rules governing the application operator. My point was more on the= usability side, as the type display is primarily intended at helping the p= rogrammer to quickly figure out type mismatch. So I'd think having a di= splay allowing to quickly distinguish between the noe and castro functions = below would be a good thing, especially for beginners. I've been using = ocaml for a few years now, and I have to say that it's not a major issu= e any more - just wanted to give some feedback about this.

Thanks
Gilles


# let noe a b =3D a;;
val noe : 'a -= > 'b -> 'a =3D <fun>
# let castro a =3D fun _ -> = a;;
val castro : 'a -> 'b -> 'a =3D <fun>

On Sun, Oct 11, 2009 at 2:17 PM, Damien Guichard= <alphablock@o= range.fr> wrote:
=A0
Hi Gilles,
=A0
The type display routine uses right-= associativity=20 of the -> operator as a rewriting rule.
Thus ('a -> 'a -> f= loat) and=20 'a -> ('a -> float) are the same type and are both=A0displayed as=A0'a -> '= ;a ->=20 float.
=A0
The type=A0'a -> ('a -= > float)=20 means=A0the application=A0will be (f x) y which is actually the=20 same as=A0f x y because the application is=20 left-associative.
The typer system doesn't care ab= out your actual=20 code syntax, and rightly so because=A0the typer system is about=20 semantic.
You intend to write=A0(f x) y, yet=20 the type system tells you intend to write=A0f x y, that's quite= =20 disturbing at first encounter.
=A0
Suffice to say you have to get your = head around=20 it.
Mind the right-associativity of ->= ; and the=20 left-associativity of application.
Think your code more semantically an= d less=20 syntactically.
In the end=A0this type sytem makes you a better= =20 programmer.
=A0
- damien
=A0
=A0

En r=E9ponse au message=
de=20 : Gilles Pirio
du :=20 2009-10-11=A021:57:40
CC :
Sujet : Re: [Caml= -list]=20 Re: Improving OCaml's choice of type to display
=A0

On the same topic, I was wonderi= ng why the=20 type of the ampl_scalar_app function below was displayed as ('a -> &= #39;a ->=20 float) -> 'a -> 'a -> float rather than ('a -> '= ;a -> float) ->=20 'a -> ('a -> float). The latter would make my life easier.
# let=20 ampl_scalar_app f p =3D if f p p > 1. then fun x->f x p else fun x-&g= t;f p=20 x;;
val ampl_scalar_app : ('a -> 'a -> float) -> 'a= -> 'a ->=20 float =3D <fun>

PS: I can imagine this has been discussed exte= nsively=20 before, feel free to just send my a link to the relevant discussion if that= 's=20 the case :)

Giles


On Sun, Oct 11, 2009 at 8:24 AM, Jun Furuse <jun.furuse@gmail.com>=20 wrote:
I=20 have not tested it well but it counts dots and should try to find
the= =20 minimal one.

A problem I have found so far is that it prints somet= hing=20 confusing, ex.

module M =3D struct type t end
module N =3D stru= ct type t=20 end
open M
open N

let _ =3D ( 1 : M.t )

>> Erro= r: This=20 expression has type int but an expression was expected of type t =A0=20 =A0(which t ?!?!?)

If there are types M.t and N.t and the both of = M=20 and N are opened,
these types are printed just "t". This can= be avoided by=20 testing the
result name "t" against the current typing envri= onment to see=20 it
really means the original type "M.t". This requires more = coding=20 but
the weekend has ended in the far east already :-) =A0 (It's 0:= 24=20 Monday
now.)

Jun

On Mon, Oct 12, 2009 at 12:12 AM, Yaron Minsky <yminsky@gmail.com> wrote:<= br>> Cool!=20 =A0That was quick.
>
> Does this patch also implement stephen= 's=20 fewest-number-of-dots heuristic? =A0I
> was thinking one nice=20 approach would be fewest-number-of-dots with ties
> broken by lengt= h of=20 final identifier.
>
> Y
>
> Yaron=20 Minsky
>
> On Oct 11, 2009, at 10:57 AM, Jun Furuse <jun.furuse@gmail.com>=20 wrote:
>
>> I have quickly wrote a small patch against 3.1= 1.1=20 for this feature, to
>> see what it would be=20 like.
>>
>>
http://sites.g= oogle.com/a/furuse.info/jun/hacks/other-small-ocaml-patches
>>=
>>=20 With this patch, path names are printed without opened modules in=20 the
>> context. It also tries heuristic data type name=20 simplification: if a
>> variant/record data type is an alias of= =20 another data type whose name
>> is shorter than the original, th= e=20 printer uses the latter.
>>
>> For=20 example:
>>
>> # open Hashtbl;;
>> # let tbl = =3D=20 Hashtbl.create 10;;
>> val tbl : ('_a, '_b) t =3D <ab= str> =A0=20 =A0 =A0(* not Hashtbl.t, since Hashtbl is
>> open=20 *)
>>
>> # type t =3D int;;
>> type t =3D=20 int
>> # type long_name =3D int;;
>> type long_name =3D= =20 int
>> # (1 : t);;
>> - : t =3D 1 =A0 =A0 =A0 =A0=20 =A0 =A0 =A0 =A0 =A0 =A0 (* t is the shorter than its=20 original type
>> int *)
>> # (1 : long_name);;
>&= gt; -=20 : int =3D 1 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (*=20 int is shorter name for long_name. t
>> is even shorter but not= =20 aliased unfortunatelly. *)
>>
>> I warn you that the pa= tch=20 is very quickly written and not tested well.
>>=20 Enjoy!
>>
>> Jun
>>
>> On Fri, Oct 9,= 2009=20 at 10:53 AM, Yaron Minsky <yminsky@gmail.com>=20 wrote:
>>>
>>> And you can compete to come up wit= h the=20 most innocuous code that comes up
>>> with the longest type.= =20 =A0Here's my current favorite:
>>>
>>> # open= =20 Option.Monad_infix;;
>>> # Map.find m 3 >>| fun x ->= x +=20 1;;
>>> - : int Core.Std.Option.Monad_infix.monad =3D Some=20 4
>>>
>>> Which of course could be rendered=20 as:
>>>
>>> # open=20 Option.Monad_infix;;
>>> # Map.find m 3 >>| fun x ->= x +=20 1;;
>>> - : int option =3D Some 4
>>>
>>= >=20 y
>>>
>>> On Thu, Oct 8, 2009 at 9:40 PM, Yaron M= insky=20 <yminsky@gmail.= com>=20 wrote:
>>>>
>>>> Anyone who plays around wi= th=20 the Core library that Jane Street just
>>>> released can s= ee=20 showcased a rather ugly detail of how Core's design
>>>&g= t;=20 interacts with how OCaml displays types.=20 =A0Witness:
>>>>
>>>> #=20 Int.of_string;;
>>>> - : string -> Core.Std.Int.stringa= ble =3D=20 <fun>
>>>> # Float.of_string;;
>>>> -= :=20 string -> Core_extended.Std.Float.stringable =3D=20 <fun>
>>>>
>>>> I'd be much happi= er if=20 this was rendered in the following equally
>>>>=20 correct
>>>> and more readable=20 form:
>>>>
>>>> #=20 Int.of_string;;
>>>> - : string -> Int.t =3D=20 <fun>
>>>> # Float.of_string;;
>>>> -= :=20 string -> Float.t =3D <fun>
>>>>
>>>&= gt; Or=20 even:
>>>>
>>>> #=20 Int.of_string;;
>>>> - : string -> int =3D=20 <fun>
>>>> # Float.of_string;;
>>>> -= :=20 string -> float =3D <fun>
>>>>
>>>>= ; And=20 this isn't just an issue in the top-level. The compiler=20 also
>>>> displays
>>>> types in the same= =20 difficult to read form. =A0I'm wondering if anyone has
>>>= ;>=20 some
>>>> thoughts as to what we can do to make the compil= er=20 make better choices
>>>> here. =A0There are two issues to= =20 overcome:
>>>>
>>>> Dropping the module nam= e.=20 =A0I'd love to give the compiler the hint that
>>>>=20 Core.Std. could be dropped from the prefix in a context where=20 that
>>>> module is
>>>> open. =A0This is= =20 what's done with the pervasives module already, I
>>>>= believe,=20 so
>>>> it seems like it should be doable=20 here.
>>>> Choosing shorter names. =A0This one seems harde= r,=20 but there are various
>>>> different possibilities for wha= t=20 type name to print out, and a
>>>>=20 reasonable
>>>> heuristic to use might be to pick the shor= test=20 one. =A0Part of the reason
>>>> these issues come up is ou= r=20 use of standardized interface components
>>>>=20 (that's
>>>> where the "stringable" type nam= e comes from).=20 =A0I suspect this one will
>>>> be
>>>> har= d=20 to fix, sadly.
>>>>
>>>> Anyway, we'd b= e happy=20 with any suggestions on how to improve=20 matters.
>>>>
>>>>=20 y
>>>
>>>
>>>=20 _______________________________________________
>>> Caml-list= =20 mailing list. Subscription management:
>>> http:/= /yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
>>>=20 Archives: http://caml.= inria.fr
>>> Beginner's list: http://groups.yahoo.com/= group/ocaml_beginners
>>>=20 Bug reports: http://caml.inria.fr/bin/caml-bugs
>>>
>>>=
>

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

_______________________________________________
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


--0015175ce094abcd380475afbdf5--