Got a little riddle, I was wondering if you could help me explain.
Define a function that returns a list:
let f = replicate 3
What we want to do is match this function with an infinite list, combine the results, and then take only those things that match the predicate.
takeWhile (< 3) $ concatMap f [1..]
Excellent! This returns [1,1,1,2,2,2] what I want.
Now I want to do something similar, but the f function now completes its results in Monad. In my usecase, this is the IO monad, but this works to discuss my problem:
let f' x = Just $ replicate 3 x
For matching and concat, I can use:
fmap concat $ mapM f' [1..5]
This returns: Just [1,1,1,2,2,2,3,3,3,4,4,4,5,5,5]
If I want to use takeWhile , this still works:
fmap (takeWhile (< 3) . concat) $ mapM f' [1..5]
Which returns: Only [1,1,1,2,2,2]. Excellent!
But, if I create a list by which I map an infinite list, this does not do what I expected:
fmap (takeWhile (< 3) . concat) $ mapM f' [1..]
It seems that takeWhile never happens. Somehow, I don't get the lazy calculations that I expected. I lost a little.