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
-
This release follows on from the last release (which featured the new
StreamT
type): we can now merge and zip multiple streams. There's also an update to thePrelude.parse*
functions (like theOption<int>
returningparseInt
).Merging
Merging multiple
StreamT
streams 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:
odds
andevens
and 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
parseInt
and its variants (parseLong
,parseGuid
, etc.) all returnOption<A>
whereA
is 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 (thinkNone
inOption
, but alsoErrors.None
in 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
parseInt
with the newparseInt<M>
:To see how this helps, take a look at the
run
function from theSumOfSquares
example:Before:
After
We lift directly into the
IO
monad instead of intoOption
first (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
Option
bearingparse*
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