Map each element of the input to a stream and then concurrently
evaluate and concatenate the resulting streams. Multiple streams may
be evaluated concurrently but earlier streams are perferred. Output
from the streams are used as they arrive.
Definition:
>>> parConcatMap modifier f stream = Stream.parConcat modifier $ fmap f stream
Examples:
>>> f cfg xs = Stream.fold Fold.toList $ Stream.parConcatMap cfg id $ Stream.fromList xs
The following streams finish in 4 seconds:
>>> stream1 = Stream.fromEffect (delay 4)
>>> stream2 = Stream.fromEffect (delay 2)
>>> stream3 = Stream.fromEffect (delay 1)
>>> f id [stream1, stream2, stream3]
1 sec
2 sec
4 sec
[1,2,4]
Limiting threads to 2 schedules the third stream only after one of the
first two has finished, releasing a thread:
>>> f (Stream.maxThreads 2) [stream1, stream2, stream3]
...
[2,1,4]
When used with a Single thread it behaves like serial concatMap:
>>> f (Stream.maxThreads 1) [stream1, stream2, stream3]
...
[4,2,1]
>>> stream1 = Stream.fromList [1,2,3]
>>> stream2 = Stream.fromList [4,5,6]
>>> f (Stream.maxThreads 1) [stream1, stream2]
[1,2,3,4,5,6]
Schedule all streams in a round robin fashion over the available
threads:
>>> f cfg xs = Stream.fold Fold.toList $ Stream.parConcatMap (Stream.interleaved True . cfg) id $ Stream.fromList xs
>>> stream1 = Stream.fromList [1,2,3]
>>> stream2 = Stream.fromList [4,5,6]
>>> f (Stream.maxThreads 1) [stream1, stream2]
[1,4,2,5,3,6]