简体   繁体   中英

Haskell - Will lazy evaluation cause this foldr to stop evaulating all functions

func1, func2.. are all defined :: [String]-> Bool

will the following fold stop evaluating the functions as soon as the first true is hit

foldr (\x acc -> acc ||  x ) False ( fmap ($ "111") [func1,func2, func3, func4])

Thinking about it I realized the fmap will evaluate all 4 functions then pass a [Bool] to the fold.. which should stop fold as soon as it hits a True.

I guess the question I need to ask is if there is a way to merge the fmap into the fold so it stops evaluating as soon as one of the functions returns true.

A function like your

foldr (\x acc -> acc || x) False

has already been written for you. It is in the standard library under the name or . Note that it flips the order of arguments to (||) , which is necessary for the short-circuiting you want. So, you can simplify your problem to

or . map ($ "111") $ fs

And happily, the idea of mapping a function over a list and or -ing together its results is also very common: witness any . So we can rewrite your whole expression to

any ($ "111") fs

so that we don't have to worry at all about the details: the people who wrote any were careful to not evaluate more of the list than necessary, so it's a solved problem from your point of view.

Your foldr function uses || the wrong way around. You probably mean to write:

foldr (\x acc -> x || acc) False

Once you make that change, no, not all functions will be evaluated. You can see for yourself with Debug.Trace

main = print $ foldr (\x acc -> x || acc) False (fmap ($ True) [id, not, traceShowId, not])

This will print only one True , showing that the third function in the list isn't forced.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM