Search code examples
haskellfunctional-programmingfold

How to break out from a fold function in haskell when the accumulator met a certain condition?


I'm calculating the sum of a list after applying someFunction to every element of it like so:

sum (map someFunction myList)

someFunction is very resource heavy so to optimise it I want to stop calculating the sum if it goes above a certain threshold.

It seems like I need to use fold but I don't know how to break out if it if the accumulator reaches the threshold. My guess is to somehow compose fold and takeWhile but I'm not exactly sure how.


Solution

  • One of the options would be using scanl function, which returns a list of intermediate calculations of foldl.

    Thus, scanl1 (+) (map someFunction myList) will return the intermediate sums of your calculations. And since Haskell is a lazy language it won't calculate all the values of myList until you need it. For example:

    take 5 $ scanl1 (+) (map someFunction myList)
    

    will calculate someFunction 5 times and return the list of these 5 results.

    After that you can use either takeWhile or dropWhile and stop the calculation, when a certain condition is True. For example:

    head $ dropWhile (< 1000) $ scanl1 (+) [1..1000000000]
    

    will stop the calculation, when sum of the numbers reaches 1000 and returns 1035.