From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 D1C17BBAF for ; Fri, 13 Aug 2010 01:14:26 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AkMCAJkdZExKfVIqmGdsb2JhbACBRJMJi2AIFQEBAQEBCAkMBxEiokqLIgEFjyMBBIU6 X-IronPort-AV: E=Sophos;i="4.55,360,1278280800"; d="scan'208,217";a="57028372" Received: from mail-ww0-f42.google.com ([74.125.82.42]) by mail2-smtp-roc.national.inria.fr with ESMTP; 13 Aug 2010 01:14:25 +0200 Received: by wwf26 with SMTP id 26so21767wwf.3 for ; Thu, 12 Aug 2010 16:14:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:references :in-reply-to:subject:date:organization:message-id:mime-version :content-type:x-mailer:thread-index:content-language; bh=YA1BKs9tEuftCpXbCvoG7AdapU4ISZMboBExSWzdXi0=; b=AdTd7HAohsmmzZ+T4SzZkput4CUwwjiQ4CFKjt193XXeAni9fqk3ucoTelDAIq4ucX UXME8d07hF98ufNEYGKxso59yYOWx73a6js2hlqQFe2hFhx5lfg9Hf8RckjD/yYSk1Iy 097aZG+GxdzeZEKX7QBV8vfOHRRVQfdKqnAZE= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=from:to:cc:references:in-reply-to:subject:date:organization :message-id:mime-version:content-type:x-mailer:thread-index :content-language; b=w3nBfYWrSwg6FeGRIm8XjQ8oXmFnv9awBKAcjA2Z2kT25i1+1gedjhYL9ZntP4or3/ Ra4sHz9+LzpGdOtUjv1vXDcgmG6r8OxJXBoiyfoBCoD8kJS5CxPxAqzP7h1JGs1nOCSj gk7ri+VSj8Teb9plwplj9vDTLBXDW8jmq/8+M= Received: by 10.227.143.12 with SMTP id s12mr705127wbu.125.1281654865558; Thu, 12 Aug 2010 16:14:25 -0700 (PDT) Received: from WinEight ([87.113.155.108]) by mx.google.com with ESMTPS id a1sm1695569wbb.2.2010.08.12.16.14.21 (version=SSLv3 cipher=RC4-MD5); Thu, 12 Aug 2010 16:14:23 -0700 (PDT) From: Jon Harrop To: "'Jeremy Bem'" , "'Jon Harrop'" Cc: "'bluestorm'" , "'caml-list List'" , "'Florian Weimer'" References: <877hk1m1df.fsf@mid.deneb.enyo.de> <87bp9dkkca.fsf@mid.deneb.enyo.de> <4c5f194e.8644d80a.7fef.69e6@mx.google.com> <03fb01cb3955$76093770$621ba650$@com> In-Reply-To: Subject: RE: [Caml-list] interest in a much simpler, but modern, Caml? Date: Fri, 13 Aug 2010 00:14:19 +0100 Organization: Flying Frog Consultancy Message-ID: <009e01cb3a74$193f5770$4bbe0650$@com> MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_009F_01CB3A7C.7B03BF70" X-Mailer: Microsoft Office Outlook 12.0 Thread-Index: Acs5tFhja6ItLvdwTMqDPpU5/IodeAAvmn7A Content-Language: en-gb X-Spam: no; 0.00; bool:01 delimited:01 overloading:01 hashing:01 cheers:01 ocaml's:01 runtime:01 abstraction:01 ocamllex:01 pervasives:01 syntax:01 ocaml:01 overloading:01 minimalist:01 higher-order:01 This is a multi-part message in MIME format. ------=_NextPart_000_009F_01CB3A7C.7B03BF70 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Presumably, in general, that would need to be: If Bool.(Int.(x=42) || Int.(x=45)) . At which point things start to look hairy. To be honest, I see this delimited overloading as the best of a bad job in the absence of equality types or per-type functionality. I think what we really want is to be able to define custom equality, comparison and hashing on types when structural versions are not applicable. F#'s solution is pretty good. Type classes are a generalization but I do not see that they buy you much for the added complexity. I'd have thought this (at least equality types) would be worth putting in a minimalistic language because it is so useful. Cheers, Jon. From: Jeremy Bem [mailto:jeremy1@gmail.com] Sent: 12 August 2010 01:22 To: Jon Harrop Cc: bluestorm; caml-list List; Florian Weimer Subject: Re: [Caml-list] interest in a much simpler, but modern, Caml? On Wed, Aug 11, 2010 at 9:02 AM, Jon Harrop wrote: What happens when you do: if Int.(x = 42 || x = 45) then ... else ... Presumably it either barfs on the assumption that "||" refers to bitwise-or between ints, or we're back to inventing progressively more absurd operator names for each individual combination of types over which they might work. How so? I think this is a borderline case (even in C++, "||" does not refer to bitwise-or). But even if Int.(||) *were* defined as some sort of integer operation, one could simply write: if Int.(x = 42) || Int.(x = 45) Also, I think the discussion has shifted. For me, the local open is a reasonably appealing way to stop using OCaml's exotic polymorphic operators whose behavior depends on the runtime representation and which don't respect type abstraction. (For example, ocamllex uses Pervasives.(=) to test whether Map's are empty, but this breaks if the Map representation changes.) Moreover the syntax even maintains OCaml compatibility thanks to the recent update. But now we seem to be talking about operator overloading, and I'm just not convinced it's necessary at all in a system with a minimalist aesthetic. Back to the local opens, I find that I'm hesitant to add so many of them, especially for equality. Polymorphic equality is hardly unnatural, after all (cf. higher-order logic). I wonder, do any practical languages use quotient types to implement custom equality predicates? In principle, Pervasives.(=) ought to be the "finest" reasonable equivalence relation on a type, which could then be coarsened: type foo = Foo of int | Goo of string let _ = assert (Foo 3 <> Goo "3") (* duh *) let foo_equiv x y = match x, y with Foo a, Foo b -> a=b | Goo a, Goo b -> a=b | Foo a, Goo b | Goo b, Foo a -> string_of_int a = b type goo = foo / foo_equiv (* automatically creates goo_of_foo *) let _ = assert (goo_of_foo (Foo 3) = goo_of_foo (Goo "3")) This would require runtime support. I envision that every "goo" is a block whose tag is "Quotient_tag" and which stores a "foo_equiv" closure in its first Obj field. As it happens, this approach would dovetail with my plans for an integrated proof assistant. Of course it lacks the "conservatism" I've been promoting :) -Jeremy ------=_NextPart_000_009F_01CB3A7C.7B03BF70 Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

Presumably, in general, that would need to = be:

 

  If Bool.(Int.(x=3D42) || Int.(x=3D45)) = …

 

At which point things start to look hairy. To be honest, = I see this delimited overloading as the best of a bad job in the absence of = equality types or per-type functionality. I think what we really want is to be = able to define custom equality, comparison and hashing on types when structural versions are not applicable. F#’s solution is pretty good. Type = classes are a generalization but I do not see that they buy you much for the = added complexity.

 

I’d have thought this (at least equality types) = would be worth putting in a minimalistic language because it is so = useful.

 

Cheers,

Jon.

 

From: Jeremy Bem = [mailto:jeremy1@gmail.com]
Sent: 12 August 2010 01:22
To: Jon Harrop
Cc: bluestorm; caml-list List; Florian Weimer
Subject: Re: [Caml-list] interest in a much simpler, but modern, = Caml?

 

On Wed, Aug 11, 2010 at 9:02 AM, Jon Harrop <jonathandeanharrop@goog= lemail.com> wrote:

 

What happens when you do:

 if Int.(x =3D 42 || x =3D 45) then ... else ...

Presumably it either barfs on the assumption that "||" refers = to bitwise-or
between ints, or we're back to inventing progressively more absurd = operator
names for each individual combination of types over which they might = work.

 

How so?  I think this is a borderline case = (even in C++, "||" does not refer to bitwise-or).  But even if = Int.(||) *were* defined as some sort of integer operation, one could simply = write:

  if Int.(x =3D 42) || Int.(x =3D = 45)

 

Also, I think the discussion has shifted.  For = me, the local open is a reasonably appealing way to stop using OCaml's exotic polymorphic operators whose behavior depends on the runtime = representation and which don't respect type abstraction.  (For example, ocamllex uses Pervasives.(=3D) to test whether Map's are empty, but this breaks if the = Map representation changes.)  Moreover the syntax even maintains OCaml compatibility thanks to the recent update.  But now we seem to be = talking about operator overloading, and I'm just not convinced it's necessary at = all in a system with a minimalist aesthetic.

 

Back to the local opens, I find that I'm hesitant = to add so many of them, especially for equality.  Polymorphic equality is = hardly unnatural, after all (cf. higher-order logic).  I wonder, do any = practical languages use quotient types to implement custom equality predicates? =  In principle, Pervasives.(=3D) ought to be the "finest" = reasonable equivalence relation on a type, which could then be = coarsened:

 

type foo = =3D Foo of int | Goo of string

let _ =3D = assert (Foo 3 <> Goo "3") (* duh *)

let = foo_equiv x y =3D

  match x, y with

    Foo a, Foo b -> a=3Db

  | Goo a, Goo b -> a=3Db

  | Foo a, Goo b

  | Goo b, Foo a -> string_of_int a =3D b

type goo = =3D foo / foo_equiv (* automatically creates goo_of_foo *)

let _ =3D = assert (goo_of_foo (Foo 3) =3D goo_of_foo (Goo = "3"))

 

This would require runtime support.  I = envision that every "goo" is a block whose tag is "Quotient_tag" = and which stores a "foo_equiv" closure in its first Obj = field.

 

As it happens, this approach would dovetail with my = plans for an integrated proof assistant.  Of course it lacks the "conservatism" I've been promoting :)

 

-Jeremy

 

------=_NextPart_000_009F_01CB3A7C.7B03BF70--