From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 870EBBBAF for ; Wed, 10 Nov 2010 15:13:39 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AjgBAP422kzRVdY2kGdsb2JhbACDOpBJgVSMVwgVAQECCQkMBxEDH6MfiSSCVAEFjhsBBIEigzVzkFU X-IronPort-AV: E=Sophos;i="4.59,178,1288566000"; d="scan'208";a="77615933" Received: from mail-bw0-f54.google.com ([209.85.214.54]) by mail4-smtp-sop.national.inria.fr with ESMTP; 10 Nov 2010 15:13:38 +0100 Received: by bwz2 with SMTP id 2so785749bwz.27 for ; Wed, 10 Nov 2010 06:13:38 -0800 (PST) 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:content-transfer-encoding:x-mailer:thread-index :content-language; bh=KgXvXqKsuJMwCfgzAOutS9LRFaxJn7wO029xK2MTy3o=; b=l9xglHN7zrksD2mPWGfO4oM4/Fplg3sA7tjNKrI6LROFaYk7TaD2Vw1Y7dem4Dqi0Y H39Uj5h3K6QtakPDgETUbaYmRjpE1UgKi5KbbHAf5a75kDn5Rr+b4V/JXDQXaUKRzZov P6LwCx1CNq5zuA6oikhwXPjyGBnoP8IHNU6LA= 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:content-transfer-encoding :x-mailer:thread-index:content-language; b=cGLQ/RG70Y/XUm+8eIB7JwxhCDSlBd61WLTxqQm6xZNopwpfZYmvveC8vepHEvzghn 0mOwVYNSj0PomnxhE3Z8h0FpPsYAhLjGdfvjCcsMF7eYJUi1C940ZgAca9nLLvPh26gi teRIn0QwtWT5kmO90gHl0jCzokKxvlleZdu0w= Received: by 10.204.51.144 with SMTP id d16mr8142386bkg.170.1289398417606; Wed, 10 Nov 2010 06:13:37 -0800 (PST) Received: from WinEight ([87.112.186.137]) by mx.google.com with ESMTPS id o7sm314310fal.27.2010.11.10.06.13.35 (version=SSLv3 cipher=RC4-MD5); Wed, 10 Nov 2010 06:13:36 -0800 (PST) From: Jon Harrop To: , , , Cc: References: <1289396667803@names.co.uk> In-Reply-To: <1289396667803@names.co.uk> Subject: RE: [Caml-list] Infix function composition operator Date: Wed, 10 Nov 2010 14:13:14 -0000 Organization: Flying Frog Consultancy Message-ID: <022001cb80e1$6afeee00$40fcca00$@com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Mailer: Microsoft Office Outlook 12.0 Thread-Index: AcuA3WdVx2Em58KuSh2nz2biqmnINAAAsu9w Content-Language: en-gb X-Spam: no; 0.00; infix:01 ocaml:01 val:01 val:01 parser:01 combinators:01 compilation:01 mls:01 haskell:01 ocaml:01 parser:01 combinators:01 ocamlyacc:01 camlp:01 cheers:01 In OCaml, the value restriction leads to non-generalized type variables = ('_a etc.) if you try to define functions like: # let ( << ) f g x =3D f(g x);; val ( << ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b =3D # let cons h t =3D h::t;; val cons : 'a -> 'a list -> 'a list =3D # cons << cons;; - : '_a -> ('_a list -> '_a list) list -> ('_a list -> '_a list) list = =3D This is a silly example but you are most likely to hit this problem in = practice in the context of parser combinators. Due to JIT compilation, = F# cannot relax the value restriction so that does not even compile. In MLs, you usually want the eta-expanded form: # let cons2 x =3D (cons << cons) x;; val cons2 : 'a -> ('a list -> 'a list) list -> ('a list -> 'a list) list = =3D But a pipeline is prettier: # let ( |> ) x f =3D f x;; val ( |> ) : 'a -> ('a -> 'b) -> 'b =3D # let cons2 x =3D x |> cons |> cons;; val cons2 : 'a -> ('a list -> 'a list) list -> ('a list -> 'a list) list = =3D This is one advantage of Haskell over OCaml/F#. However, I don't see it = as a useful advantage in practice because parser combinators are so = tedious during development (they require constant attention as types = evolve): you want code generation like ocamlyacc or camlp4. OCaml is a = very strong contender here, of course. Cheers, Jon. > -----Original Message----- > From: mark@proof-technologies.com [mailto:mark@proof-technologies.com] > Sent: 10 November 2010 13:44 > To: jonathandeanharrop@googlemail.com; yminsky@gmail.com; > arlen@noblesamurai.com > Cc: caml-list@inria.fr > Subject: Re: [Caml-list] Infix function composition operator >=20 > So how does value restriction affect things here? (excuse my lack of > knowledge) >=20 > One thing about using a pipeline like this is that it relies on '|>' > being > left-associative (which it is due to OCaml's convention on operators > that > start with "|"). >=20 > Mark. >=20 >=20 > on 10/11/10 12:52 PM, Jon Harrop > wrote: >=20 > > A pipeline operator is usually preferred over function composition = in > impure > > languages like OCaml and F# due to the value restriction. For > example, > your > > example would be written in F# as: > > > > x |> op1 |> op2 |> op3 |> op4 |> op5 > > > > This style is very common in F#, particularly when dealing with > collections. > > > > Cheers, > > Jon. > > > >> -----Original Message----- > >> From: caml-list-bounces@yquem.inria.fr [mailto:caml-list- > >> bounces@yquem.inria.fr] On Behalf Of mark@proof-technologies.com > >> Sent: 10 November 2010 07:00 > >> To: yminsky@gmail.com; arlen@noblesamurai.com > >> Cc: caml-list@inria.fr > >> Subject: Re: [Caml-list] Infix function composition operator > >> > >> on 10/11/10 3:45 AM, yminsky@gmail.com wrote: > >> > >> > This is probably a minority opinion, but I have written and read > >> quite a > >> lot > >> > of OCaml code over the years, and I've seen surprisingly few > >> effective > >> uses > >> > of the composition operator. Somehow, I usually find that code > that > >> avoids > >> > it is simpler and easier to read. > >> > >> I agree that using a composition operator can make the code obtuse, > and > >> so > >> should not be overused. But it's incredibly useful for certain > >> situations: > >> > >> 1) If you are performing a long chain of composed operations, it > avoids > >> nested bracketing piling up. > >> > >> For example: > >> (op5 <<- op4 <<- op3 <<- op2 <<- op1) x > >> Instead of: > >> op5 (op4 (op3 (op2 (op1 x)))) > >> > >> This sort of thing happens quite a lot in certain applications, = e.g. > in > >> language processing, to get at subexpressions. > >> > >> 2) Creating an anonymous function to be passed as an argument, it > >> avoids > >> explicitly mentioning arguments of that function. > >> > >> This sort of thing can happen a lot in functional programming > >> generally. > >> > >> For example: > >> List.map (op2 <<- op1) xs > >> Instead of: > >> List.map (fun x -> op2 (op1 x)) xs > >> > >> Mark Adams > >> > >> _______________________________________________ > >> 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 > > > > > > > >