Suppose I have a function representing some computation that can fail
f :: a -> Maybe b
If I have a list l, I can find the first (when scanning left-to-right) item in the list on which f succeeds using findList f l, where findList is the following function
findList :: (a -> Maybe b) -> [a] -> Maybe b
findList f [] = Nothing
findList f (x : xs) = case f x of
Nothing -> findList f xs
Just y -> Just y
(or using, e.g., firstJust from the extra package).
Question.
What do I do if I want to do the same thing with a Set from containers?
That is, I want a function with signature
findSet :: (a -> Maybe b) -> Set a -> Maybe b
which is equivalent to
findSet f s = findList f (Set.toList s)
The line above works as an implementation. However, I don't want to create the intermediate list Set.toList s (even with lazy evaluation, there is still some unnecessary overhead, right?).
I also don't want to iterate over the entire set once a successful item has been found, as in the following implementation:
findSet f s = foldl g Nothing s
where
g Nothing x = f x
g (Just y) _ = Just y
So is there a good way of traversing over a set "left-to-right", applying a computation that can fail to each member, and stopping at the first successful result?