2

my goal is to write a times function of type int list -> int that that takes a list of ints and, using continuations, returns an int such that that int = multiplication of all the ints in the int list. for instance times [2;2;3] returns 12.

Here is what I have so far:

let times l = 
 let rec times' l c = match l with
 | [] -> c []
 | h::h2::t -> times' (h*h2::t) (fun r -> c ( r))
 | h :: [] -> times' [] (fun r -> c (h::[]))
 in
  times' l (fun r -> r) ;; 

Problems with my code

  1. it returns an int list with one element which is the result (multiplication of all ints in the inputed int list)

  2. I feel like this is not really using continuations, this seems to be a normal tail recursive function but I am not sure since I am still not very familiar with this programming style.

glennsl
  • 28,186
  • 12
  • 57
  • 75
TeamPlayer
  • 21
  • 2
  • I can't see how you'd be able to implement CPS with a function of that type at all. I would think it should instead be `int list -> (int -> unit) -> unit`. – glennsl Dec 11 '18 at 23:06
  • Oh sorry I thought any function that could be written in a tail_recursive manner can be re-written using CPS :o is this not true then ? – TeamPlayer Dec 11 '18 at 23:09
  • CPS is passing the "return" value via the continuation, which means the function _doesn't_ return, at least within the context of CPS. To get the external function to return a value normally you'd have to return that value through the entire "CPS" call chain, which means it's not CPS, just tail recursion. – glennsl Dec 11 '18 at 23:25
  • It should be true that you can rewrite any tail recursive function as CPS, but not without changing the type signature. – glennsl Dec 11 '18 at 23:26
  • In continuation passing style, functions do not "return" as we do in the default style. – Marcelo Camargo Dec 12 '18 at 11:53
  • You can rewrite any program in continuation passing style, not only tail recursive functions, a nice property is that when you do so all the calls become tail calls. – Cactus Dec 14 '18 at 08:15

1 Answers1

1

You did computation in arguments in manner of recursive calls, but you should do it in continuation. For CPS, what you should do is to "grow" a given continuation.

let times l =
  let rec aux l c =
    match l with
    | [] -> c 1  (* I assume that (times []) is one, and pass it to the next computation c. *)
    | n::ns -> aux ns (fun x -> c (n * x))  (* In a new continuation: For a given value x, multiply by n, and pass it to the next computation c. *)
  in aux l (fun r -> r)

Also, examples which explain differences between CPS and direct style, written in "Continuation-passing style" in Wikipedia may help.

nekketsuuu
  • 1,641
  • 1
  • 21
  • 26