I was trying to find a directory name by appending a number until I found a name that doesn't yet exist:
head <$> filterM (fmap not . fexists_) [ getDatedDir t d n | n <- [0..] ]
The problem with this is that it never returns. I think the problem is that although IO is a Functor, filterM has to do all the IO before the head effects; that is, it has to evaluate fexists for every n - and that's of course infinite.
Now, I can solve this:
go t d 0
where go t d n = do
let dir = getDatedDir t d n
fexists_ dir >>= \case
False -> return dir
True -> go t d (n+1)
But I feel that there ought to be a more elegant approach, using filterM or something similar.
This feels like a common enough pattern that there is probably an extisting function in Control.Monad, I'm just not seeing it.