[SOLVED] fibonacci cps implementation

Issue

This Content is from Stack Overflow. Question asked by mxbr236

Currently I’m trying to convert different function from tail recursive to cps (continuation passing style) using OCaml language.

Normally, I managed to do a sum and factorial function:

Sum function:

Tail recursive:

let sum n =
  let rec subSum n acc =
    match n with
    |0 -> acc
    |_ -> subSum (n-1) (n+acc)
  in subSum n 0;;

Printf.printf "%un" (sum 5);; (*returns 15*)

cps version:

let sum2 n =
  let rec sum_cps n acc =
    match n with
    |0 -> acc 0
    |_ -> sum_cps (n-1) (fun r -> acc (n+r))
  in sum_cps n (fun n -> n);;

Printf.printf "%un" (sum2 5);; (*returns 15*)

factorial (same style as sum):

tail recursive:

let fact n =
  let rec subFact n acc =
    match n with
    |0 -> acc
    |1 -> acc
    |_ -> subFact (n-1) (n*acc)
  in subFact n 1;;

Printf.printf "%un" (fact 6);; (*returns 720*)

cps version:

let fact2 n =
  let rec fact_cps n acc =
    match n with
    |0 -> acc 1
    |1 -> acc 1
    |_ -> fact_cps (n-1) (fun r -> acc (n*r))
  in fact_cps n (fun n -> n);;

Printf.printf "%un" (fact2 6);; (*returns 720*)

However, in fibonacci, there is another argument in addition to the accumulator and that disturbs me a little bit:

tail recursive version:

let fibo n =
  let rec fibon n acc prev =
    match n with
    |0 -> acc
    |_ -> fibon (n-1) (prev+acc) acc
  in fibon n 0 1;;

Printf.printf "%un" (fibo 6);; (*returns 8*)

cps attempt (not working):

let fibo n =
  let rec fibo_cps n acc prev =
    match n with
    |0 -> 0
    |_ -> fibo_cps (n-1) (fun r -> acc (prev+r)) acc
  in fibo_cps n (fun n -> n) 1L;;

I would just like to understand how to make a working cps version of fibonacci.



Solution

I think this is what you’re looking for –

let fibo n =
  let rec fibo_cps n acc =
    match n with
    |0 -> acc 0
    |1 -> acc 1
    |_ -> fibo_cps (n-1) (fun x -> fibo_cps (n-2) (fun y -> acc (x+y)))
  in fibo_cps n (fun x -> x)

Please note that while the computation above is tail-recursive, it’s still a very inefficient way to compute fibonacci numbers. Consider a linear iterative algorithm –

let fibo2 n =
  let rec aux n a b =
    match n with
    |0 -> a 
    |_ -> aux (n-1) b (a+b)
  in aux n 0 1


This Question was asked in StackOverflow by mxbr236 and Answered by Mulan It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?