caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* How to add () to function parameters
@ 2009-10-14 10:44 Till Crueger
  2009-10-16 15:15 ` [Caml-list] " Till Varoquaux
  0 siblings, 1 reply; 3+ messages in thread
From: Till Crueger @ 2009-10-14 10:44 UTC (permalink / raw)
  To: caml-list

Hi,

I am looking for a way to add a unit parameter to a function that takes an  
arbitrary number of parameters. If the number of parameters is known this  
is fairly easy and I can just do:

let lift1 f a =
    fun () ->
       f a;;

let lift2 f a b =
    fun () ->
      f a b;;

(all these create one closure per lifting)
etc...

However it is a bit of a hassle to have to code each of these lifts... So  
what I am looking for is a way to extend this pattern to all numbers. So  
far I got to the point that I can do the following:

let lift_once f a =
    fun () ->
       f a;;

let lift_more f a =
    fun () ->
       f () a;;

So for a function f taking two parameters a and b I can do

lift_more (lift_once f a) b
(two closures created)

and for a function taking the parameters a, b and c I can do

lift_more (lift_more (lift_once f a) b) c
(three closures created)

to get the lifted functions.

However this solution gets quite ugly with all the parentheses. Also there  
are a lot of closures being produced and evaluated for any single lifting.  
I had a look at the Jane Street blog post about variable argument  
functions (http://ocaml.janestcapital.com/?q=node/22), which seems to do  
similar things. However I have never been really good with CPS, so I don't  
know if those techniques can be applied to this problem.

Is there any way to do this, which does not get this ugly. Also the  
resulting lifted function should not contain too many closures.

Thanks for your help,
    Till


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

* Re: [Caml-list] How to add () to function parameters
  2009-10-14 10:44 How to add () to function parameters Till Crueger
@ 2009-10-16 15:15 ` Till Varoquaux
  2009-10-16 15:22   ` Till Varoquaux
  0 siblings, 1 reply; 3+ messages in thread
From: Till Varoquaux @ 2009-10-16 15:15 UTC (permalink / raw)
  To: Till Crueger; +Cc: caml-list

Well I can basically see two solutions (plus countless complications
that I won't go into.)

We want to define a function

val cps3: f:('a -> 'b -> 'c -> 'd) -> ('d -> 'e) -> 'a -> 'b -> 'c -> 'e =

that takes a three argument function a returns the same function in CPS style.

The functional unparsing/danvy way [1]:

> let (++) f g = fun x -> f (g x)
> let i k f arg = k (f arg)
> let cps ty ~f k = ty k f
> let cps3 ~f = cps (i++i++i) ~f

brute force style:

> let e acc ~f cont = acc cont f
> let i = fun acc g -> g (fun cont v arg -> acc cont (v arg))
> let cps = fun z ->
>   let acc = (fun cont x -> cont x) in
>   z acc
> let cps3 ~f = cps i i i e ~f

The first style is an acquired taste quite the same way that monad
are. With some getting use to and abstracting your types in a sensible
way you can enclose things quite nicely and define elegant
printf/scanf kind of functions.

I strongly discourage you to use the second style. It is a very
reworked mlton.fold [2] style solution. mlton's fold is a lot more
esoteric and leads to types that I have never been able to abstract
properly.

Till

[1] http://www.brics.dk/RS/98/12/
[2] http://mlton.org/Fold

On Wed, Oct 14, 2009 at 6:44 AM, Till Crueger <Till.Crueger@gmx.net> wrote:
> Hi,
>
> I am looking for a way to add a unit parameter to a function that takes an
> arbitrary number of parameters. If the number of parameters is known this is
> fairly easy and I can just do:
>
> let lift1 f a =
>   fun () ->
>      f a;;
>
> let lift2 f a b =
>   fun () ->
>     f a b;;
>
> (all these create one closure per lifting)
> etc...
>
> However it is a bit of a hassle to have to code each of these lifts... So
> what I am looking for is a way to extend this pattern to all numbers. So far
> I got to the point that I can do the following:
>
> let lift_once f a =
>   fun () ->
>      f a;;
>
> let lift_more f a =
>   fun () ->
>      f () a;;
>
> So for a function f taking two parameters a and b I can do
>
> lift_more (lift_once f a) b
> (two closures created)
>
> and for a function taking the parameters a, b and c I can do
>
> lift_more (lift_more (lift_once f a) b) c
> (three closures created)
>
> to get the lifted functions.
>
> However this solution gets quite ugly with all the parentheses. Also there
> are a lot of closures being produced and evaluated for any single lifting. I
> had a look at the Jane Street blog post about variable argument functions
> (http://ocaml.janestcapital.com/?q=node/22), which seems to do similar
> things. However I have never been really good with CPS, so I don't know if
> those techniques can be applied to this problem.
>
> Is there any way to do this, which does not get this ugly. Also the
> resulting lifted function should not contain too many closures.
>
> Thanks for your help,
>   Till
>
> _______________________________________________
> 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] 3+ messages in thread

* Re: [Caml-list] How to add () to function parameters
  2009-10-16 15:15 ` [Caml-list] " Till Varoquaux
@ 2009-10-16 15:22   ` Till Varoquaux
  0 siblings, 0 replies; 3+ messages in thread
From: Till Varoquaux @ 2009-10-16 15:22 UTC (permalink / raw)
  To: Till Crueger; +Cc: caml-list

Oh, and I nearly forgot: In practice you shouldn't really have that
many functions taking more than 5 unlabeled arguments lying around so
I would bite the bullet and define cps1 through 5 the straightforward
way....

Till

On Fri, Oct 16, 2009 at 11:15 AM, Till Varoquaux <till@pps.jussieu.fr> wrote:
> Well I can basically see two solutions (plus countless complications
> that I won't go into.)
>
> We want to define a function
>
> val cps3: f:('a -> 'b -> 'c -> 'd) -> ('d -> 'e) -> 'a -> 'b -> 'c -> 'e =
>
> that takes a three argument function a returns the same function in CPS style.
>
> The functional unparsing/danvy way [1]:
>
>> let (++) f g = fun x -> f (g x)
>> let i k f arg = k (f arg)
>> let cps ty ~f k = ty k f
>> let cps3 ~f = cps (i++i++i) ~f
>
> brute force style:
>
>> let e acc ~f cont = acc cont f
>> let i = fun acc g -> g (fun cont v arg -> acc cont (v arg))
>> let cps = fun z ->
>>   let acc = (fun cont x -> cont x) in
>>   z acc
>> let cps3 ~f = cps i i i e ~f
>
> The first style is an acquired taste quite the same way that monad
> are. With some getting use to and abstracting your types in a sensible
> way you can enclose things quite nicely and define elegant
> printf/scanf kind of functions.
>
> I strongly discourage you to use the second style. It is a very
> reworked mlton.fold [2] style solution. mlton's fold is a lot more
> esoteric and leads to types that I have never been able to abstract
> properly.
>
> Till
>
> [1] http://www.brics.dk/RS/98/12/
> [2] http://mlton.org/Fold
>
> On Wed, Oct 14, 2009 at 6:44 AM, Till Crueger <Till.Crueger@gmx.net> wrote:
>> Hi,
>>
>> I am looking for a way to add a unit parameter to a function that takes an
>> arbitrary number of parameters. If the number of parameters is known this is
>> fairly easy and I can just do:
>>
>> let lift1 f a =
>>   fun () ->
>>      f a;;
>>
>> let lift2 f a b =
>>   fun () ->
>>     f a b;;
>>
>> (all these create one closure per lifting)
>> etc...
>>
>> However it is a bit of a hassle to have to code each of these lifts... So
>> what I am looking for is a way to extend this pattern to all numbers. So far
>> I got to the point that I can do the following:
>>
>> let lift_once f a =
>>   fun () ->
>>      f a;;
>>
>> let lift_more f a =
>>   fun () ->
>>      f () a;;
>>
>> So for a function f taking two parameters a and b I can do
>>
>> lift_more (lift_once f a) b
>> (two closures created)
>>
>> and for a function taking the parameters a, b and c I can do
>>
>> lift_more (lift_more (lift_once f a) b) c
>> (three closures created)
>>
>> to get the lifted functions.
>>
>> However this solution gets quite ugly with all the parentheses. Also there
>> are a lot of closures being produced and evaluated for any single lifting. I
>> had a look at the Jane Street blog post about variable argument functions
>> (http://ocaml.janestcapital.com/?q=node/22), which seems to do similar
>> things. However I have never been really good with CPS, so I don't know if
>> those techniques can be applied to this problem.
>>
>> Is there any way to do this, which does not get this ugly. Also the
>> resulting lifted function should not contain too many closures.
>>
>> Thanks for your help,
>>   Till
>>
>> _______________________________________________
>> 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] 3+ messages in thread

end of thread, other threads:[~2009-10-16 15:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-14 10:44 How to add () to function parameters Till Crueger
2009-10-16 15:15 ` [Caml-list] " Till Varoquaux
2009-10-16 15:22   ` Till Varoquaux

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