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=AWL,DNS_FROM_RFC_POST, 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 4038ABBC4 for ; Wed, 1 Apr 2009 03:24:42 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AmkBAJhe0klKfSwdimdsb2JhbACNGog7PwEBAQoJDAcPBaZaB4EBkAgBAwEDg3cGhTg X-IronPort-AV: E=Sophos;i="4.38,431,1233529200"; d="scan'208";a="26756626" Received: from yx-out-2324.google.com ([74.125.44.29]) by mail1-smtp-roc.national.inria.fr with ESMTP; 01 Apr 2009 03:24:41 +0200 Received: by yx-out-2324.google.com with SMTP id 8so1895226yxm.3 for ; Tue, 31 Mar 2009 18:24:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:reply-to:to:subject:date :user-agent:cc:references:in-reply-to:content-type :content-transfer-encoding:content-disposition:message-id; bh=6NcbvgWs7p4yeIk33A5JgV8MarPlnNEIphqcVYC90m0=; b=peN9NB60K3uYq1vaxkwXXL+TnPD3ycCEXNaWKPRTIsQYlaGHzfaPxTM0N0OJ+8VSon t86pDlCuB7osaG2frqbL2fuJn2Y/DYXnp3tGponjbU+3SsOkfIhrYpbXxm59XPLFaP4S PjmzF2d5eOPiZE9zrtG1/sJ5yTdzGO+d8tpiE= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:reply-to:to:subject:date:user-agent:cc:references:in-reply-to :content-type:content-transfer-encoding:content-disposition :message-id; b=WNcJ7uZGuJKUVOmps20rqo/ktXvgQ6w4hjKCOkcechypDLPyJ8ZE71wVBWPqd1z2Ug ZRBTwzxO5M+HPgeOyt3hkh6LAe9CuZC9dMF5Q9HWQ9QhPPuAStXS9qyA7sykod5qGVGD WTzgMGw6iM82spKkh56Mbik8NjLqSsP/IqUoI= Received: by 10.90.70.6 with SMTP id s6mr3732066aga.71.1238549080574; Tue, 31 Mar 2009 18:24:40 -0700 (PDT) Received: from ?192.168.0.102? (c-98-219-43-7.hsd1.ga.comcast.net [98.219.43.7]) by mx.google.com with ESMTPS id 17sm2595907agd.47.2009.03.31.18.24.39 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 31 Mar 2009 18:24:39 -0700 (PDT) From: Peng Zang Reply-To: peng.zang@gmail.com To: caml-list@yquem.inria.fr Subject: Re: [Caml-list] Bug? Constraints get ignored in methods Date: Tue, 31 Mar 2009 21:24:36 -0400 User-Agent: KMail/1.9.9 Cc: Goswin von Brederlow References: <87ab71ic1f.fsf@frosties.localdomain> In-Reply-To: <87ab71ic1f.fsf@frosties.localdomain> Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200903312124.38637.peng.zang@gmail.com> X-Spam: no; 0.00; bug:01 hash:01 mylist:01 escapes:01 ocaml:01 recursive:01 coercions:01 recursive:01 cheers:01 subset:01 ocaml:01 subset:01 val:01 mutable:01 val:01 -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi, Here's an example of how constraints are specified for polymorphic methods. In this example I define a list type which can compare to anything that is foldable. class type ['a] foldable = object method foldl : 'z. ('z -> 'a -> 'z) -> 'z -> 'z end class type ['a] mylist = object inherit ['a] foldable method compare : 'z. ('a #foldable as 'z) -> int end Direct application to your example would not work: # class virtual base = object method virtual setnext : 'a. (#base as 'a) option -> unit end Error: This type scheme cannot quantify 'a : it escapes this scope. # OCaml does not allow the recursive reference when the method is polymorphic. One option is to just deal with coercions or a function that does it for you: class virtual base = object method virtual setnext : base option -> unit end let callsetnext (obj:#base) (n:#base option) = obj#setnext (n :> base option) Another option is to factor out the basic operations you need like the in list example. I didn't make the list compare method work with other lists, I made it more general to work with anything that is foldable. This avoids the recursive reference because foldable is defined ahead of time. Cheers, Peng On Tuesday 31 March 2009 06:05:00 pm Goswin von Brederlow wrote: > Hi, > > I want to keep a linked list of structures that have a common subset > of functionality. I thought this would be a good use of ocaml objects. > A base class with the common subset of functionality and methods to > link them. And then derived classes for the specific types. Most > simplified it looks like this: > > # class type base_type = object val mutable next : base_type option method > set_next : base_type option -> unit end;; class type base_type = > object > val mutable next : base_type option > method set_next : base_type option -> unit > end > > # class base : base_type = object val mutable next = None method set_next n > = next <- n end;; class base : base_type > > # class foo = object inherit base method foo = () end;; > class foo : > object > val mutable next : base_type option > method foo : unit > method set_next : base_type option -> unit > end > > # let a = new base in > let b = new foo in > a#set_next (Some (b :> base_type));; > - : unit = () > > # let a = new base in > let b = new foo in > a#set_next (Some b);; > ^ > Error: This expression has type foo but is here used with type base_type > The second object type has no method foo > > This last error isn't nice. I don't want to have to cast the objects > all the time. So I thought there must be a better way using > polymorphic methods with a constraint. But here is where everything > breaks down. First lets look at just the set_next method: > > # class type virtual vbase_type = object method virtual set_next : 'a. 'a > option -> unit constraint 'a = #vbase_type end;; class type virtual > vbase_type = > object method virtual set_next : 'a option -> unit end > > # class virtual vbase : vbase_type = object method virtual set_next : 'a. > 'a option -> unit constraint 'a = #vbase_type end;; class virtual vbase : > vbase_type > > # class base = object inherit vbase method set_next _ = () end;; > class base : object method set_next : 'a option -> unit end > > # let b = new base;; > val b : base = > > # b#set_next (Some 1);; > - : unit = () > > Huh? That should not work. 1 is not a superset of #vbase_type. The > constraint gets completly ignored by ocaml. Adding back the next gives > further problems: > > # class type virtual vbase_type = object val mutable next : #vbase_type > option method virtual set_next : 'a. 'a option -> unit constraint 'a = > #vbase_type end;; class type virtual vbase_type = > object > val mutable next : #vbase_type option > method virtual set_next : 'a option -> unit > end > > # class virtual vbase : vbase_type = object val mutable next = None method > virtual set_next : 'a. 'a option -> unit constraint 'a = #vbase_type end;; > class virtual vbase : vbase_type > > # class base = object inherit vbase > method set_next n = next <- (n :> vbase_type option) end;; > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > Error: This method has type #vbase_type option -> unit > which is less general than 'a. 'a option -> unit > > Again I blame ocaml for dropping the constraint. Given the constraint > the type would be correct. > > > > So how do I have to specify the set_next method that any superset of > #base_type will be accepted as argument? Or is that a bug in ocaml and > my syntax is perfectly fine? > > MfG > Goswin > > _______________________________________________ > 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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.7 (GNU/Linux) iD8DBQFJ0sJWfIRcEFL/JewRAr9iAKDXaZNlIZDlCdTaxWrIy7+5nObIZgCeIJ2d qcvcX2pc/F899JuMgRa3S4A= =lNOb -----END PGP SIGNATURE-----