Reputation: 9264
here is my code:
boolTrueList :: [Bool] -> Bool
boolTrueList xs
| length (filterFalse xs) > 0 = False
| otherwise = True
where
filterFalse = filter (==False)
This is perfectly working, however I would like to rewrite the same thing with foldr/foldl, but I am stuck.
My idea is to fold a list until I find a false value and then, stop. Any hint?
Upvotes: 0
Views: 1882
Reputation: 3830
There's a way to think about folds that I have found very useful and intuitive (I probably read this somewhere). Please note this may not lead to the most efficient solution, but my concern here is with clarity.
Don't think of fold as a function that builds a value from a list, and instead think of it as a way to insert an operator between elements of the list. When you do that, fold then becomes a way of transforming a list into an expression. So for example, the following:
foldr op I [A,..,Z]
Will produce the following expansion:
A op .. op Z op I
If you apply that thinking to your issue, all you need to do is ask yourself what should op and I be to ensure that you only get True if A .. Z are True? As a hint, I is usually the identity element with respect to op (a value that doesn't change the expression, like 0 would be for addition).
Well, we know from logic that and (&&) is only true if ALL its operands are true. Likewise, True is the identity element with respect to &&. So with that said, your expansion would be:
A && .. && Z && True
So your fold would be:
foldr (&&) True [A,..,Z]
Which means your function would be:
boolTrueList x = foldr (&&) True x
Or in a more point-free style:
boolTrueList = foldr (&&) True
It isn't enough to use higher-order functions to avoid iteration, we should avoid the iterative mindset. Think in terms of open-ended expressions and not "at this point, this value will propagate". More often than not, iterations are simply low level ways of generating open-ended expressions, and because our languages forced us to do this, our mindset has often been stuck at it, even when we have languages that allow us to think at the expression level.
Upvotes: 5
Reputation: 183888
My idea is to fold a list until I find a false value and then, stop. Any hint?
If you want to stop early, you have to use foldr
. foldl
always has to traverse the entire list (so doesn't work at all on infinite lists).
So you want
foldr combine default list
The default
is the result for an empty list, that would be True
here. Now, how would we want to combine?
When a False
is encountered, we want to return False immediately, so
combine False _ = False
and when the value is True
, we must go on, so
combine True more = more
In other words, combine = (&&)
, so
boolTrueList = foldr (&&) True
or, even shorter
boolTrueList = and
Upvotes: 12