I Streamed a Stream

Ivan Lazar Miljenovic

23 May, 2018

Why do this Code-Jam?

What’s wrong with the status-quo?

  • Monads are great for specifying I/O.
  • But default lazy I/O in Haskell is broken.
    • (Except in certain specific cases.)
    • (Maybe not broken, but difficult to get right.)

What’s the solution?

Stream Processing!

… no, not parallel programming …

… and not just for Haskell …

[…] P J Landin’s original use for streams was to model the histories of loop variables, but he also observed that streams could have been used as a model for I/O in ALGOL 60.

A Survey Of Stream Processing, R. Stephens, 1995

Stream processing defines a pipeline of operators that transform, combine, or reduce (even to a single scalar) large amounts of data. Characteristically, data is accessed strictly linearly rather than randomly and repeatedly – and processed uniformly. The upside of the limited expressiveness is the opportunity to process large amount of data efficiently, in constant and small space.

Oleg Kiselyov, http://okmij.org/ftp/Streams.html

Possible Implementations

  • Iteratees (Oleg Kiselyov, 2008)
  • iteratee (John Lato, 2009 – 2014)
  • enumerator (John Millikin, 2010 – 2011)
  • conduit (Michael Snoyman, 2011 –)
  • pipes (Gabriel Gonzalez, 2012 –)
  • machines (Edward Kmett, 2012 –)
  • io-streams (Gregory Collins, 2013 –)
  • quiver (Patryk Zadarnowski, 2015)
  • streaming (Michael Thompson, 2015 –)
  • streamly (Harendra Kumar, 2017 –)

Why streaming?

  • It’s simpler!
  • Stream (Of a) m r ≈ m ([a], r)
  • Standard function composition! No need for new operators!
  • Gaining popularity for cases not needing extra power of pipes, conduit, etc.

A nice example

A not-so-nice example

Exercises

Where to get them?

How to do them?

Look at that convenient README!

Exercise 0

Build yourself a Stream!

Time for some basic Haskell!

… does anyone want to do this?

Results

  • Basic understanding of the Stream type
    • Lists interspered with monads!
  • How to manually decompose it
  • Hopefully a desire not to manually decompose in practice.

Exercise 1

Functor Streaming

What’s with that f in Stream f m r?

Results

  • Know why Stream can take any functor
  • Basic understanding of how Streams can contain other Streams
  • How Streams compare to pipes and conduits.

Exercise 2

Streams of Streams

  • Stream f m (Stream f m r)
    • Leftovers (ala Conduit)
  • Stream f (Stream g m) r
    • A stream created as a Monadic effect
  • Stream (Stream f m) m r
    • An actual stream of streams (e.g. grouping).
  • Stream (Of (Stream f m v)) m r
    • Don’t think this is useful
  • Stream (ByteString m) m r
    • Using streaming-bytestring.

Results

  • Know why we might want to compose Streams in different ways.

Exercise 3

Streams are powerful lists

Including the infamous infinite Fibonacci definition!

Results

  • I can stop telling you how Streams are list-like.

Exercise 4

How to do I/O

The whole reason we started this!

Results

  • How to do I/O with Streams.
  • Resource management best practices.

Exercise 5

Tying it all together!

Try to actually do something with what you’ve (hopefully) learnt today!

Results

Celebrate

Stream on!