Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Stream Processing and Functional Programming

αλεx π
September 10, 2015
720

Stream Processing and Functional Programming

Everyone's doing Stream Processing these days. During last 5 years there's been more CEP engines released than Web Frameworks. This is a great pattern, but without Functional Programming concepts you're just touching a surface. How to make your streams immutable, composable and reusable, and why many out-of-the-box distributions are limiting your basically endless opportunities.
Stateful streams is a current state-of-art. Although much too often state makes the Stream less composable and performant. People are using stores such as Redis to store the intermediate state, and never think about better ways to make state available for every worker.

With currently existing single-box RX Frameworks and Message Queues it's possible to build Streams in ways that entirely change the perspective and thinking about the stream, taking complexity out and letting developers think about each entity in a stream as an isolated event, allowing better composition and testability.

αλεx π

September 10, 2015
Tweet

Transcript

  1. Currying ((a → b) → c) → (a → (b

    → c)) = λf. λx. λy. f (x, y)
  2. Closures BiFunction<Integer, Integer, Integer> fn = (a, b) -> a

    + b; Function<Integer, Function<Integer, Integer>> curried = a -> { return (b) -> a + b; };
  3. Pipe data Step a i = Yield a i |

    Skip i data Pipe a = Pipe (i -> Step a i) i - - Monads in Stream type omitted for brevity
  4. Stream is a Functor fmap id = id fmap (g

    . h) = (fmap g) . (fmap h) class Functor f where fmap :: (a -> b) -> f a -> f b Functor Laws morphism, mapping between categories
  5. Stream is an Applicative pure id <*> v = v

    pure f <*> pure x = pure (f x) u <*> pure y = pure ($ y) <*> u u <*> (v <*> w) = pure (.) <*> u <*> v <*> w class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b Applicative Laws
  6. Basic Stream Operations map (Stream s) :: (a -> b)

    -> s a -> s b filter (Stream s) :: (a -> Boolean) -> s a -> s a slide (Stream s) :: ([a] -> [a]) -> s a -> s [a] partition (Stream s) :: ([a] -> Boolean) -> s a -> s [a] consume (Stream a) :: (a -> IO ()) -> s a -> s a
  7. Firehose<Key> firehose = new Firehose<>(); firehose.on(Key.wrap("myKey"), (v) -> { /*

    ... */} ); firehose.notify(Key.wrap("key1"), 1); Example
  8. (SRC source, DST destination, Function<V, V1> mapper) -> { firehose.on(source,

    (SRC key, V value) -> { firehose.notify(destination, mapper.apply(value)); } }); return new NamedPipe<>(firehose); } Implementation Idea
  9. NamedPipe<Integer> intPipe = new NamedPipe<>(); intPipe.map("key1", "key2", (i) -> i

    + 1); intPipe.map("key2", "key3", (i) -> i * 2); intPipe.consume("key2", System.out::println); Example
  10. private final Key upstream; private final NamedPipe pipe; <V1> AnonymousPipe<V1>

    map(Function<V, V1> mapper) { Key downstream = upstream.derive(); pipe.map(upstream, downstream, mapper); return new AnonymousPipe<>(downstream, pipe); } Implementation Idea
  11. Example NamedPipe<Integer> pipe = new NamedPipe<>(); pipe.anonymous("key") .map((i) -> i

    + 1) .map(i -> i * 2) .consume(System.out::println); pipe.notify("key", 1);
  12. Implementation Idea <V1> MatchedPipe<V1> map(Function<V, V1> mapper) { this.suppliers.add((Key src,

    Key dst, NamedPipe<V1> pipe) -> { return (key, value) -> { pipe.notify(dst, mapper.apply(value)); }; }); return new MatchedPipe<>(suppliers); }
  13. Example NamedPipe<Integer> pipe = new NamedPipe<>(); pipe.matched(key -> key.startsWith("key")) .map(i

    -> i + 1) .map(i -> i * 2) .consume(System.out::println); pipe.notify("key1", 1); pipe.notify("key2", 2); pipe.notify("key3", 3);
  14. Reordering a • b = b • a ∀ a,b

    ∈ S (a • b) • c = a • (b • c) ∀ a,b, c ∈ S Commutativity Associativity
  15. Use Cases Decoupling independent actions Data pipelining, aggregation Building blocks

    for any async actions Database Drivers Request/Response servers