StreamT merging and zipping + parsing updates #1351
louthy
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
This release follows on from the last release (which featured the new
StreamTtype): we can now merge and zip multiple streams. There's also an update to thePrelude.parse*functions (like theOption<int>returningparseInt).Merging
Merging multiple
StreamTstreams has the following behaviours:If either stream finishes first, the rest of the stream that still has items keeps yielding its own items.
There is an example of merging on in the Streams sample:
This creates two streams:
oddsandevensand them merges them into a single stream using:The output looks like this:
With differing colours depending on whether odd or even.
You can merge any number of streams with the
&operator, or concatenate streams with the+operator.Other ways to merge:
Zipping
You can zip up to four streams and the result is a stream of tuples.
Obviously, to create a tuple all of the streams need to have yielded a value and so must wait for them on each stream. But, be sure that the async streams are running independently and not blocking before being tupled.
That also means the length of the tuple stream is clamped to the shortest stream length.
Useful aspects of zipping sync and async is that you can pair async events with identifiers:
For example, imagine you have a stream of messages coming from an external source (async):
And a stream of natural numbers, playing the role of an identifier (sync):
Then you can tag each message with a unique identifier like so:
There's also an example in the Streams sample. It's similar to the merging example, except, instead of interleaving the odd and even streams, it tuples them:
The output looks like this:
There are no operators for zipping (because operators don't support generics), these are the options:
Parsing
parseIntand its variants (parseLong,parseGuid, etc.) all returnOption<A>whereAis the type being generated from the parse. With the advent of the trait-types - in particular theAlternative<M>trait - we can now parse to any type that implements theAlternative<M>trait.Alternative<M>is like a monoid for higher-kinds and it has anEmpty<A>()function that allows us to construct a 'zero' version of higher-kind (thinkNoneinOption, but alsoErrors.Nonein types with an alternative value ofError).The original
parse*functions (that returnOption), remain unchanged, but there is now an extra overload for each variant that takes the trait-implementation type as a generic parameter:Here's the original
parseIntwith the newparseInt<M>:To see how this helps, take a look at the
runfunction from theSumOfSquaresexample:Before:
After
We lift directly into the
IOmonad instead of intoOptionfirst (only to have to match on it straight away).Obviously, the default alternative value might not be right, and so you can then use the
|operator to catch the failure:Instead of raising an error, you could also provide a default if the parse fails:
This is nice and elegant and, I think, shows the usefulness of the traits. I wouldn't mind removing the
Optionbearingparse*functions, but I don't think it hurts to keep them in.As always, any questions or comments, please reply below.
This discussion was created from the release StreamT merging and zipping + parsing updates.
Beta Was this translation helpful? Give feedback.
All reactions