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=none autolearn=disabled version=3.1.3 Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by yquem.inria.fr (Postfix) with ESMTP id DD18EBB83 for ; Fri, 1 Sep 2006 20:40:10 +0200 (CEST) Received: from mallaury.nerim.net (smtp-105-friday.noc.nerim.net [62.4.17.105]) by nez-perce.inria.fr (8.13.6/8.13.6) with ESMTP id k81IeAWC028706 for ; Fri, 1 Sep 2006 20:40:10 +0200 Received: from karryall.dnsalias.org (karryall.dnsalias.org [213.41.240.180]) by mallaury.nerim.net (Postfix) with ESMTP id AA07A4F3DE; Fri, 1 Sep 2006 20:39:58 +0200 (CEST) Received: by karryall.dnsalias.org (Postfix, from userid 500) id D1634596DD3; Fri, 1 Sep 2006 20:40:06 +0200 (CEST) From: Olivier Andrieu MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <17656.32390.653089.859246@karryall.dnsalias.org> Date: Fri, 1 Sep 2006 20:40:06 +0200 To: "David Allsopp" Cc: "OCaml List" Subject: Re: [Caml-list] Polymorphic variants question In-Reply-To: <012901c6cdec$64edf490$6a7ba8c0@treble> References: <012901c6cdec$64edf490$6a7ba8c0@treble> X-Mailer: VM 7.19 under Emacs 21.4.1 X-Miltered: at nez-perce with ID 44F87E8A.000 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Spam: no; 0.00; andrieu:01 oandrieu:01 variants:01 variants:01 constructors:01 val:01 bool:01 bool:01 lexers:01 high-level:01 lexers:01 subset:01 lexer:01 type-checker:01 val:01 David Allsopp [Friday 1 September 2006] : > > Forgive the potentially obvious question --- I'm not very familiar with > polymorphic variants but I think that they're what I want in this situation! > > Suppose I'm dealing with three constructors `A, `B and `C and I have a > function f that's supposed to take either `A or `C and return any of `A, `B > or `C. If I write: > > let f x = if x = `A then (true, `B) else (false, x) > > then I get the type > > val f : ([> `A | `B] as 'a) -> bool * 'a > > Now, if I try to constrain it to what I'm after with > > let (f : [`A | `C] -> bool * [`A | `B | `C]) = fun x -> ... > > then I get a type error unless I change > (false, x) > to > (false, id x) > with > let id = function `A -> `A | `C -> `C > > Is there a better way of writing this? I'm using this in the context of > several interrelated lexers where `A, `B and `C are high-level states and > certain lexers can only be called in a subset of those states but each lexer > may yield any value for the next-state. I'd quite like to eliminate the id x > bit since it's only there to "separate" x from the return value for the > type-checker. you can use pattern-matching with a "as" pattern to introduce another identifier for your value in the non-`A branch : ,---- | # let f = function | | `A -> true, `B | | `C as x -> false, x ;; | val f : [< `A | `C ] -> bool * [> `B | `C ] = `---- (the [> `B | `C ] return type can be constrained to [`A`B|`C] if you want) -- Olivier