Search code examples
listf#continuationsstack-overflow

F# continuations goes on StackOverflowException


Hi guys I'm implementing an F# function that takes two lists of type : (int*float) list. These two lists have different lentgths. The int element of the couple is an increasing code. What I wanted to do is create a new list that will contain a couple (int*float) for each two elements of the two lists that have the same code. It's important to note that codes in lists are in increasing order. These lists are probably a little long, like 2-3000 elements., so I tried to implement this function using continuation passing style in order to avoid StackOverflowExceptions. but sadly i failed.

This is the function, i hope you will give me any hints!

let identifiedDifference list1 list2 =
    let rec produceResult (l1, l2) k =
        match l1,l2 with
            | [],[] 
            | _,[]
            | [],_ -> k []
            | (code,rate:float)::xs, (code2,rate2)::ys -> 
                if code = code2 
                    then
                        produceResult (xs, ys) (fun c -> (code,Math.Abs(rate-rate2))::(k c))
                    elif code > code2
                        then produceResult (l1, ys) k
                        else produceResult (xs, l2) k
    produceResult (list1, list2) id

I've done something wrong?


Solution

  • (fun c -> (code,Math.Abs(rate-rate2))::(k c))
    

    should be

    (fun c ->  k ((code,Math.Abs(rate-rate2))::c))
    

    to make it tail-recursive:

    let identifiedDifference list1 list2 =
        let rec produceResult (l1, l2) k =
            match l1,l2 with
                | [],[] 
                | _,[]
                | [],_ -> k []
                | (code,rate:float)::xs, (code2,rate2)::ys -> 
                    if code = code2 then produceResult (xs, ys) (fun c ->  k ((code,Math.Abs(rate-rate2))::c))
                    elif code > code2 then produceResult (l1, ys) k
                    else produceResult (xs, l2) k
        produceResult (list1, list2) id
    

    This will also fix your results being returned in reverse order.