How to add () to function parameters

View: New views
3 Messages — Rating Filter:   Alert me  

How to add () to function parameters

by Till Crueger-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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

Re: How to add () to function parameters

by Till Varoquaux-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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

_______________________________________________
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

Re: How to add () to function parameters

by Till Varoquaux-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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

_______________________________________________
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