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=1.1 required=5.0 tests=AWL,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 mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by yquem.inria.fr (Postfix) with ESMTP id DB068BC69 for ; Wed, 17 Oct 2007 16:33:44 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgAAAL65FUdA6aLsmGdsb2JhbACOTgIBAQcEBhEW X-IronPort-AV: E=Sophos;i="4.21,289,1188770400"; d="scan'208";a="18139989" Received: from nz-out-0506.google.com ([64.233.162.236]) by mail4-smtp-sop.national.inria.fr with ESMTP; 17 Oct 2007 16:33:44 +0200 Received: by nz-out-0506.google.com with SMTP id x7so1442901nzc for ; Wed, 17 Oct 2007 07:33:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; bh=I/yoCv3AEQ10ICtEF8/9IeD8lfFbQbXzXP2n3jJ0gOE=; b=VcjBh6hoAXKz/jXSbDW0UCQF+mvGxQ8PUilo1hu5R8oYoebguG44NOuNtLhS6Mq3Sk4YSmpBinFQCEw1Thl0MsH6I3hD+PYO7GGHYpum2Dl178Jr62Mvhgu1px5AYfJSkFa2F2mOLHmE4d+l4TrMftEXnIVcGZPXbC7AZimpG5w= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=nmRc4tod9WZf+qgRTzOZwC00VcecdwptfxCGvtzI55dvlqzJFr5wGDbpO6nJFhVVOuUFVA1fcLJmbrvROrXPMpmpMt+RfIJ8LtWRfcu/xraMsNsZxyGGtyZgOlBfIaEF/6xwURdXj3lXy0z5g//fvBXuioTeCV1quljgRjzv+Q8= Received: by 10.114.61.1 with SMTP id j1mr9917526waa.1192631622097; Wed, 17 Oct 2007 07:33:42 -0700 (PDT) Received: by 10.114.235.16 with HTTP; Wed, 17 Oct 2007 07:33:41 -0700 (PDT) Message-ID: <875c7e070710170733h205fbe54ube172e969da65871@mail.gmail.com> Date: Wed, 17 Oct 2007 10:33:42 -0400 From: "Chris King" To: "Dario Teixeira" Subject: Re: [Caml-list] Smells like duck-typing Cc: caml-list@yquem.inria.fr In-Reply-To: <932096.75090.qm@web54602.mail.re2.yahoo.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline References: <932096.75090.qm@web54602.mail.re2.yahoo.com> X-Spam: no; 0.00; ocaml:01 val:01 val:01 failwith:01 failwith:01 printf:01 printf:01 functors:01 struct:01 sig:01 struct:01 ditch:98 polymorphic:01 wrote:01 typing:01 On 10/17/07, Dario Teixeira wrote: > c) Actually put the "Objective" part of OCaml to use. This is the solution > I am using at the moment. This is what it looks like: > > class story (id, title, intro, body) = > object > val id: int option = id > val title: string option = title > val intro: string option = intro > val body: string option = body > > method id = > match id with > | Some thing -> thing > | None -> failwith "oops" > > method title = > match title with > | Some thing -> thing > | None -> failwith "oops" > > method intro = > match intro with > | Some thing -> thing > | None -> failwith "oops" > > method body = > match body with > | Some thing -> thing > | None -> failwith "oops" > end > > > class full (id, title, intro, body) = > object > inherit story (Some id, Some title, Some intro, Some body) > end > > class blurb (id, title, intro) = > object > inherit story (Some id, Some title, Some intro, None) > end > > class fresh (title, intro, body) = > object > inherit story (None, Some title, Some intro, Some body) > end > > > let print_metadata s = > Printf.printf "%d: %s\n" s#id s#title Why not have different object types for each of the story types? e.g. type full = < id: int; title: string; intro: string; body: string > type blurb = < id: int; title: string; intro: string > type fresh = < title: string; intro: string; body: string > print_metadata can remain as is in your object example. In order to allow functions that operate differently depending on which story type they're given, use a polymorphic variant like in your first example. If you wanted print_metadata to take such a type, it could be written as: let print_metadata s = let s' = match s with | `Full f -> (f :> < id: int; title: string >) | `Blurb f -> (f :> < id: int; title: string >) in Printf.printf "%d: %s\n" s'#id s'#title (Note the match gook is unfortunately needed to get the typing right...) If on the other hand you wanted to ditch objects entirely, you could do a similar thing using modules and functors. E.g.: module Full = struct type t = { id: int; title: string; intro: string; body: string } let id s = s.id let title s = s.title let intro s = s.intro let body s = s.body end (* etc. *) module Print_metadata(S: sig type t val id: t -> string val title: t -> string) = struct let f s = Printf.printf "%d: %s\n" (S.id s) (S.title s) end Of course, since calls to print_metadata now look like "Print_metadata(Full).f story", you're essentially forced to write out the types of everything, which is probably what you wanted to avoid anyway. HTH, Chris