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=0.0 required=5.0 tests=AWL autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by yquem.inria.fr (Postfix) with ESMTP id 20A04BC6D for ; Thu, 7 Feb 2008 16:19:20 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgAAADKwqkfAXQInh2dsb2JhbACQMQEBAQgKKZte X-IronPort-AV: E=Sophos;i="4.25,316,1199660400"; d="scan'208";a="22359614" Received: from concorde.inria.fr ([192.93.2.39]) by mail4-smtp-sop.national.inria.fr with ESMTP; 07 Feb 2008 16:19:19 +0100 Received: from mail1-relais-roc.national.inria.fr (mail1-relais-roc.national.inria.fr [192.134.164.82]) by concorde.inria.fr (8.13.6/8.13.6) with ESMTP id m17FJEm6012874 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Thu, 7 Feb 2008 16:19:19 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgAAALuvqkfBvsFJn2dsb2JhbACQMQEBAQEBBgQGCQgYm2E X-IronPort-AV: E=Sophos;i="4.25,316,1199660400"; d="scan'208";a="7776608" Received: from hedwig2.umh.ac.be (HELO hedwig1.umh.ac.be) ([193.190.193.73]) by mail1-smtp-roc.national.inria.fr with ESMTP; 07 Feb 2008 16:19:17 +0100 Received: from poincare.swapping.umh.ac.be ([10.102.100.12]) by hedwig1.umh.ac.be (8.14.2/8.14.2) with ESMTP id m17FJJMS1167612; Thu, 7 Feb 2008 16:19:26 +0100 Received: from localhost ([127.0.0.1] ident=trch) by poincare.swapping.umh.ac.be with esmtp (Exim 4.68) (envelope-from ) id 1JN8W2-0006dn-Iz; Thu, 07 Feb 2008 16:18:18 +0100 Date: Thu, 07 Feb 2008 16:18:18 +0100 (CET) Message-Id: <20080207.161818.541003217877080499.Christophe.Troestler+ocaml@umh.ac.be> To: till.varoquaux@gmail.com Cc: caml-list@inria.fr Subject: Re: [Caml-list] Re: Empty polymorphic variant type From: Christophe TROESTLER In-Reply-To: <9d3ec8300802060424j6fbe3378m8ac51d14cc399d6b@mail.gmail.com> References: <9d3ec8300802060416t39660ca3r9fbcf0fd1a161d43@mail.gmail.com> <9d3ec8300802060424j6fbe3378m8ac51d14cc399d6b@mail.gmail.com> X-Face: #2fb%mPx>rRL@4ff~TVgZ"<[:,oL"`TUEGK/[8/qb58~C>jR(x4A+v/n)7BgpEtIph_neoLKJBq0JBY9:}8v|j Organization: University of Mons-Hainaut X-Mailer: Mew version 5.2.52 on Emacs 22.1 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Text/Plain; charset=iso-8859-15 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 2.1 (www dot roaringpenguin dot com slash mimedefang) X-Miltered: at concorde with ID 47AB2172.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; christophe:01 troestler:01 christophe:01 troestler:01 ocaml:01 variants:01 camlp:01 syntax:01 subtype:01 ocamlc:01 -pp:01 camlp:01 intersection:01 val:01 val:01 On Wed, 6 Feb 2008 12:24:21 +0000, Till Varoquaux wrote: > > On Feb 6, 2008 12:16 PM, Till Varoquaux wrote: > > Polymorohic variants are great to encode permissions as phantom types. > > This usage is hindered by the apparent impossibility to declare the > > empty polymorphic type. > > > > To illustrate this use case I'll take a bogus example: suppose one is > > handling accounts, you might want to be able to add a permission on > > private information (NIN, passwords etc..). So you could be handling > > accounts where you'd have read permission, write permission both or > > none. By using a polymorphic variant type: > > > > type 'a account constraint 'a = [< `Read | `Write ];; > > > Small addendum: > > type 'a account constraint 'a = [< `Permission |`Read | `Write > `Permission ];; > > would work but it seems clunky and convoluted. The empty polymorphic type may be declared with the camlp5 revised syntax but does not behave as a universal polymorphic variant subtype : $ cat a.ml type account 'a = 'b constraint 'a = [ < `Read | `Write ]; type t = account [= ]; $ ocamlc -pp camlp5r a.ml File "a.ml", line 2, characters 17-21: This type [ ] should be an instance of type [< `Read | `Write ] These two variant types have no intersection IMHO I guess your best solution for readability (at least in the code you write, not always for the generated types) ATM is to define type aliases: type 'a account constraint 'a = [< `None |`Read | `Write > `None ] type none = [ `None ] type read = [ `None | `Read ] type write = [ `None | `Write ] Then you can have : val x : [> read] account val y : [> write] account # [x; y; z];; - : [ `None | `Read | `Write ] account list = [; ; ] # let f (x : [< read ] account) = ... # let g (x : [ read | write ] account) = ... My 0.02¤, ChriS