caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Re: [Caml-list] Infix function composition operator
@ 2010-11-10  6:59 mark
  2010-11-10 12:51 ` Jon Harrop
  0 siblings, 1 reply; 13+ messages in thread
From: mark @ 2010-11-10  6:59 UTC (permalink / raw)
  To: yminsky, arlen; +Cc: caml-list

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


^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [Caml-list] Infix function composition operator
  2010-11-10  6:59 [Caml-list] Infix function composition operator mark
@ 2010-11-10 12:51 ` Jon Harrop
  2010-11-14 18:20   ` Till Varoquaux
  0 siblings, 1 reply; 13+ messages in thread
From: Jon Harrop @ 2010-11-10 12:51 UTC (permalink / raw)
  To: mark, yminsky, arlen; +Cc: caml-list

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


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Caml-list] Infix function composition operator
  2010-11-10 12:51 ` Jon Harrop
@ 2010-11-14 18:20   ` Till Varoquaux
  0 siblings, 0 replies; 13+ messages in thread
From: Till Varoquaux @ 2010-11-14 18:20 UTC (permalink / raw)
  To: Jon Harrop; +Cc: mark, yminsky, arlen, caml-list

Thank you jon; this was a very insightful answer. Brought me one of
those palm forehead moments:
Most novice programmers don't understand the value restriction and
having an infix function composition operator in your standard library
is like throwing them under the bus.
In general I find that this (value restriction) is a problem I often
hit when writing combinator libraries in ocaml.

On Wed, Nov 10, 2010 at 7:51 AM, Jon Harrop
<jonathandeanharrop@googlemail.com> wrote:
> 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
>
> _______________________________________________
> 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
>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Caml-list] Infix function composition operator
  2010-11-10 17:41     ` Jon Harrop
@ 2010-11-10 18:52       ` Stephan Tolksdorf
  0 siblings, 0 replies; 13+ messages in thread
From: Stephan Tolksdorf @ 2010-11-10 18:52 UTC (permalink / raw)
  To: Jon Harrop; +Cc: caml-list

On Wed, Nov 10, 2010 at 17:41 -0000, Jon Harrop wrote:
> I had to completely replace the serialization layer. Ideally, I would just write a script to compile my type definitions into serializers and deserializers over them. However, I haven't found time to do that yet so I am maintaining a set of combinators instead. They account for over 15% of the source code now. Every time I change a type (e.g. adding a field to a record type), I must update the combinators to reflect the changes. This is getting seriously tedious as the project is experimental and my types need to evolve rapidly.

Your problem here seems to be the absence of compile-time 
meta-programming facilities in F#, not the limitations of parser 
combinators. Using a parser generator tool like ocamlyacc (which you 
originally cited as a better technology) wouldn't make the parsing in 
your situation any easier, or am I missing something?

In the case of your server application you could probably replace the 
compile-time meta-programming with some run-time reflection & code 
generation. If you cache serializers and deserializers per type, 
performance should still be good.

- Stephan

>
>> -----Original Message-----
>> From: caml-list-bounces@yquem.inria.fr [mailto:caml-list-
>> bounces@yquem.inria.fr] On Behalf Of Stephan Tolksdorf
>> Sent: 10 November 2010 16:11
>> To: caml-list@inria.fr
>> Subject: Re: [Caml-list] Infix function composition operator
>>
>> On Wed, Nov 10, 2010 at 14:13 -0000, Jon Harrop wrote:
>>> 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.
>>
>> Could you maybe elaborate a bit on what you find tedious with regard to
>> evolving types in the context of parser combinators?
>>
>> In my parser code (using FParsec in F#) most types get inferred by the
>> compiler and in the remaining instances the type annotations can hardly
>> be called tedious. Actually, I find the types and the Visual Studio
>> tooltips with the inferred types rather helpful for development.
>>
>> - Stephan
>>
>>>
>>> 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
>>>>
>>>> So how does value restriction affect things here?  (excuse my lack
>> of
>>>> knowledge)
>>>>
>>>> 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 "|").
>>>>
>>>> Mark.
>>>>
>>>>
>>>> on 10/11/10 12:52 PM, Jon Harrop<jonathandeanharrop@googlemail.com>
>>>> wrote:
>>>>
>>>>> 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
>>>>>
>>>>>
>>>>>
>>>>>
>>>
>>> _______________________________________________
>>> 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
>>>
>>
>> _______________________________________________
>> 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
>
>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [Caml-list] Infix function composition operator
  2010-11-10 16:10   ` Stephan Tolksdorf
@ 2010-11-10 17:41     ` Jon Harrop
  2010-11-10 18:52       ` Stephan Tolksdorf
  0 siblings, 1 reply; 13+ messages in thread
From: Jon Harrop @ 2010-11-10 17:41 UTC (permalink / raw)
  To: 'Stephan Tolksdorf', caml-list

I am currently writing a concurrent server under contract in F#. Due to the poor performance of the default .NET serialization (over 170x slower than Marshal in OCaml!), I had to completely replace the serialization layer. Ideally, I would just write a script to compile my type definitions into serializers and deserializers over them. However, I haven't found time to do that yet so I am maintaining a set of combinators instead. They account for over 15% of the source code now. Every time I change a type (e.g. adding a field to a record type), I must update the combinators to reflect the changes. This is getting seriously tedious as the project is experimental and my types need to evolve rapidly.

If I were using OCaml, Marshal would be easily fast enough and I wouldn't even need to update my type definitions by hand because I could use structural typing (polymorphic variants and objects). Unfortunately, this is not yet possible in F#. Another problem area has been the incrementality of garbage collection. OCaml is good in this respect among functional languages but still orders of magnitude behind the state-of-the-art. With enough care and attention, .NET can be almost as good as OCaml is ordinarily but .NET's worse cases are horrific:

  http://flyingfrogblog.blogspot.com/2010/10/can-you-repro-this-64-bit-net-gc-bug.html

Cheers,
Jon.

> -----Original Message-----
> From: caml-list-bounces@yquem.inria.fr [mailto:caml-list-
> bounces@yquem.inria.fr] On Behalf Of Stephan Tolksdorf
> Sent: 10 November 2010 16:11
> To: caml-list@inria.fr
> Subject: Re: [Caml-list] Infix function composition operator
> 
> On Wed, Nov 10, 2010 at 14:13 -0000, Jon Harrop wrote:
> > 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.
> 
> Could you maybe elaborate a bit on what you find tedious with regard to
> evolving types in the context of parser combinators?
> 
> In my parser code (using FParsec in F#) most types get inferred by the
> compiler and in the remaining instances the type annotations can hardly
> be called tedious. Actually, I find the types and the Visual Studio
> tooltips with the inferred types rather helpful for development.
> 
> - Stephan
> 
> >
> > 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
> >>
> >> So how does value restriction affect things here?  (excuse my lack
> of
> >> knowledge)
> >>
> >> 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 "|").
> >>
> >> Mark.
> >>
> >>
> >> on 10/11/10 12:52 PM, Jon Harrop<jonathandeanharrop@googlemail.com>
> >> wrote:
> >>
> >>> 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
> >>>
> >>>
> >>>
> >>>
> >
> > _______________________________________________
> > 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
> >
> 
> _______________________________________________
> 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


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Caml-list] Infix function composition operator
  2010-11-10 14:13 ` Jon Harrop
@ 2010-11-10 16:10   ` Stephan Tolksdorf
  2010-11-10 17:41     ` Jon Harrop
  0 siblings, 1 reply; 13+ messages in thread
From: Stephan Tolksdorf @ 2010-11-10 16:10 UTC (permalink / raw)
  To: caml-list

On Wed, Nov 10, 2010 at 14:13 -0000, Jon Harrop wrote:
> 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.

Could you maybe elaborate a bit on what you find tedious with regard to 
evolving types in the context of parser combinators?

In my parser code (using FParsec in F#) most types get inferred by the 
compiler and in the remaining instances the type annotations can hardly 
be called tedious. Actually, I find the types and the Visual Studio 
tooltips with the inferred types rather helpful for development.

- Stephan

>
> 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
>>
>> So how does value restriction affect things here?  (excuse my lack of
>> knowledge)
>>
>> 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 "|").
>>
>> Mark.
>>
>>
>> on 10/11/10 12:52 PM, Jon Harrop<jonathandeanharrop@googlemail.com>
>> wrote:
>>
>>> 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
>>>
>>>
>>>
>>>
>
> _______________________________________________
> 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
>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Caml-list] Infix function composition operator
@ 2010-11-10 15:18 mark
  0 siblings, 0 replies; 13+ messages in thread
From: mark @ 2010-11-10 15:18 UTC (permalink / raw)
  To: jonathandeanharrop, jonathandeanharrop, yminsky, arlen; +Cc: caml-list

Fascinating!  I do use parser combinators myself, and find myself having to
use the eta-expanded form, like you say.  Thanks for that explanation.

Mark.


on 10/11/10 2:20 PM, Jon Harrop <jonathandeanharrop@googlemail.com> wrote:

> In OCaml, the value restriction leads to non-generalized type variables
('_a
> etc.) if you try to define functions like:
>
> # let ( << ) f g x = f(g x);;
> val ( << ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>
>
> # let cons h t = h::t;;
> val cons : 'a -> 'a list -> 'a list = <fun>
>
> # cons << cons;;
> - : '_a -> ('_a list -> '_a list) list -> ('_a list -> '_a list) list =
> <fun>
>
> 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 = (cons << cons) x;;
> val cons2 : 'a -> ('a list -> 'a list) list -> ('a list -> 'a list) list =
> <fun>
>
> But a pipeline is prettier:
>
> # let ( |> ) x f = f x;;
> val ( |> ) : 'a -> ('a -> 'b) -> 'b = <fun>
>
> # let cons2 x = x |> cons |> cons;;
> val cons2 : 'a -> ('a list -> 'a list) list -> ('a list -> 'a list) list =
> <fun>
>
> 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
>>
>> So how does value restriction affect things here?  (excuse my lack of
>> knowledge)
>>
>> 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 "|").
>>
>> Mark.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [Caml-list] Infix function composition operator
  2010-11-10 13:44 mark
@ 2010-11-10 14:13 ` Jon Harrop
  2010-11-10 16:10   ` Stephan Tolksdorf
  0 siblings, 1 reply; 13+ messages in thread
From: Jon Harrop @ 2010-11-10 14:13 UTC (permalink / raw)
  To: mark, jonathandeanharrop, yminsky, arlen; +Cc: caml-list

In OCaml, the value restriction leads to non-generalized type variables ('_a etc.) if you try to define functions like:

# let ( << ) f g x = f(g x);;
val ( << ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>

# let cons h t = h::t;;
val cons : 'a -> 'a list -> 'a list = <fun>

# cons << cons;;
- : '_a -> ('_a list -> '_a list) list -> ('_a list -> '_a list) list = <fun>

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 = (cons << cons) x;;
val cons2 : 'a -> ('a list -> 'a list) list -> ('a list -> 'a list) list =
  <fun>

But a pipeline is prettier:

# let ( |> ) x f = f x;;
val ( |> ) : 'a -> ('a -> 'b) -> 'b = <fun>

# let cons2 x = x |> cons |> cons;;
val cons2 : 'a -> ('a list -> 'a list) list -> ('a list -> 'a list) list =
  <fun>

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
> 
> So how does value restriction affect things here?  (excuse my lack of
> knowledge)
> 
> 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 "|").
> 
> Mark.
> 
> 
> on 10/11/10 12:52 PM, Jon Harrop <jonathandeanharrop@googlemail.com>
> wrote:
> 
> > 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
> >
> >
> >
> >


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Caml-list] Infix function composition operator
@ 2010-11-10 13:44 mark
  2010-11-10 14:13 ` Jon Harrop
  0 siblings, 1 reply; 13+ messages in thread
From: mark @ 2010-11-10 13:44 UTC (permalink / raw)
  To: jonathandeanharrop, yminsky, arlen; +Cc: caml-list

So how does value restriction affect things here?  (excuse my lack of
knowledge)

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 "|").

Mark.


on 10/11/10 12:52 PM, Jon Harrop <jonathandeanharrop@googlemail.com> wrote:

> 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
>
>
>
>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Caml-list] Infix function composition operator
  2010-11-10  3:19 Arlen Christian Mart Cuss
  2010-11-10  3:45 ` [Caml-list] " Yaron Minsky
@ 2010-11-10 13:23 ` Michael Ekstrand
  1 sibling, 0 replies; 13+ messages in thread
From: Michael Ekstrand @ 2010-11-10 13:23 UTC (permalink / raw)
  To: caml-list

On 11/09/2010 09:19 PM, Arlen Christian Mart Cuss wrote:
> Hi all,
> 
> I know this was asked at least 12 years ago[1], but is there any
> consensus or reason for there not being a "compose" function in standard
> OCaml, nor an infix operator?
> 
> At the moment I tend to "let compose" or "let (<<-) f g x = f (g x)",
> but I wish I didn't have to!

Batteries[1] includes such an operator in its Std module and its
extension of Pervasives.  The compose operator is is '-|', and the
reverse compose operator is '|-' ((f |- g) x = g (f x)).  It also
provides the pipeline operator '|>' and its converse application
operator '**>'.

- Michael

1. http://batteries.forge.ocamlcore.org


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Caml-list] Infix function composition operator
  2010-11-10  3:45 ` [Caml-list] " Yaron Minsky
  2010-11-10  4:37   ` Arlen Christian Mart Cuss
@ 2010-11-10 10:06   ` DS
  1 sibling, 0 replies; 13+ messages in thread
From: DS @ 2010-11-10 10:06 UTC (permalink / raw)
  To: caml-list

On 10 Nov 2010, at 4:45, Yaron Minsky wrote:
> let ( |! ) x f = f x
This is the same as F#'s pipe operator (|>) which I find extremely useful because with it code reads the way it works, not backwards:
2 |> tenfold |> add 1 |> double  => 42
(ok, this is a ridiculous example, but you get the point).
Regards.
-DS

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Caml-list] Infix function composition operator
  2010-11-10  3:45 ` [Caml-list] " Yaron Minsky
@ 2010-11-10  4:37   ` Arlen Christian Mart Cuss
  2010-11-10 10:06   ` DS
  1 sibling, 0 replies; 13+ messages in thread
From: Arlen Christian Mart Cuss @ 2010-11-10  4:37 UTC (permalink / raw)
  To: yminsky; +Cc: caml-list

Hi Yaron,

On Tue, 2010-11-09 at 22:45 -0500, Yaron Minsky 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 know what you mean - it can make some code more obtuse than just doing
the same thing with a lambda. But I can't help but get the feeling it
has a place here: (note: example is semi-contrived and there are plenty
of better ways to do this, but just as an example)

module CGI =
struct
(* ... *)
  let escape =
    let replace = Str.global_replace <<- Str.regexp_string in
    (replace "\"" "&quot;") <<- (replace "'" "&#039;") <<- (replace "&"
"&amp;")

Particularly the second line of `escape', where the escaping mechanism
is indeed a composition of the three replaces as specified.

Comparing that to this:

let escape s = 
  let replace = (* ... *) in
  replace "\"" "&quot;" (replace "'" "&#039;" (replace "&" "&amp;" s))

.. I prefer the former, as the latter forces me to specify an argument,
and nest the calls to replace. I'm not sure if there are any performance
benefits/losses as a result of computing the function `escape' in the
first example, either, but it's a consideration.

> I'm not averse to infix operators.  At Jane Street we've found the
> following sequencing operator to be highly useful:
> 
> let ( |! ) x f = f x
> 
> and it is indeed part of the default include in Jane Street's Core
> library.

That looks neat, and I imagine it to be useful, but I can't think of a
concrete use-case off the cuff. Could you give an example?

> y

Cheers,
Arlen

> On Tue, Nov 9, 2010 at 10:19 PM, Arlen Christian Mart Cuss
> <arlen@noblesamurai.com> wrote:
>         Hi all,
>         
>         I know this was asked at least 12 years ago[1], but is there
>         any
>         consensus or reason for there not being a "compose" function
>         in standard
>         OCaml, nor an infix operator?
>         
>         At the moment I tend to "let compose" or "let (<<-) f g x = f
>         (g x)",
>         but I wish I didn't have to!
>         
>         Thanks,
>         Arlen
>         
>         [1]
>         http://webcache.googleusercontent.com/search?q=cache:TcqI7o37il8J:pauillac.inria.fr/caml/caml-list/0720.html+ocaml+function+compose&cd=2&hl=en&ct=clnk&client=ubuntu
>         
>         _______________________________________________
>         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
> 
> 
> _______________________________________________
> 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



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Caml-list] Infix function composition operator
  2010-11-10  3:19 Arlen Christian Mart Cuss
@ 2010-11-10  3:45 ` Yaron Minsky
  2010-11-10  4:37   ` Arlen Christian Mart Cuss
  2010-11-10 10:06   ` DS
  2010-11-10 13:23 ` Michael Ekstrand
  1 sibling, 2 replies; 13+ messages in thread
From: Yaron Minsky @ 2010-11-10  3:45 UTC (permalink / raw)
  To: Arlen Christian Mart Cuss; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 1378 bytes --]

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'm not averse to infix operators.  At Jane Street we've found the following
sequencing operator to be highly useful:

let ( |! ) x f = f x

and it is indeed part of the default include in Jane Street's Core library.

y

On Tue, Nov 9, 2010 at 10:19 PM, Arlen Christian Mart Cuss <
arlen@noblesamurai.com> wrote:

> Hi all,
>
> I know this was asked at least 12 years ago[1], but is there any
> consensus or reason for there not being a "compose" function in standard
> OCaml, nor an infix operator?
>
> At the moment I tend to "let compose" or "let (<<-) f g x = f (g x)",
> but I wish I didn't have to!
>
> Thanks,
> Arlen
>
> [1]
>
> http://webcache.googleusercontent.com/search?q=cache:TcqI7o37il8J:pauillac.inria.fr/caml/caml-list/0720.html+ocaml+function+compose&cd=2&hl=en&ct=clnk&client=ubuntu
>
> _______________________________________________
> 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
>

[-- Attachment #2: Type: text/html, Size: 2345 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2010-11-14 18:21 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-10  6:59 [Caml-list] Infix function composition operator mark
2010-11-10 12:51 ` Jon Harrop
2010-11-14 18:20   ` Till Varoquaux
  -- strict thread matches above, loose matches on Subject: below --
2010-11-10 15:18 mark
2010-11-10 13:44 mark
2010-11-10 14:13 ` Jon Harrop
2010-11-10 16:10   ` Stephan Tolksdorf
2010-11-10 17:41     ` Jon Harrop
2010-11-10 18:52       ` Stephan Tolksdorf
2010-11-10  3:19 Arlen Christian Mart Cuss
2010-11-10  3:45 ` [Caml-list] " Yaron Minsky
2010-11-10  4:37   ` Arlen Christian Mart Cuss
2010-11-10 10:06   ` DS
2010-11-10 13:23 ` Michael Ekstrand

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).