Exploring Functional Programming and Concurrency in C++

Slide Note
Embed
Share

Dive into the world of functional programming and concurrency in C++, covering topics such as monads, higher-order functions, combinators, futures, promises, and shared states. Explore advanced concepts like move semantics, functors, currying, and more to enhance your C++ programming skills.


Uploaded on Sep 07, 2024 | 1 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. I see a monad in your future Bartosz Milewski

  2. Functional Patterns in C++ Concurrency First class functions Generic programming Memory Management (move semantics) Math nomenclature Functor Applicative Functor Monad Monoid

  3. Higher Order Functions for_each(v.begin(), v.end(), [](char c) { cout << c; }); transform(v.begin(), v.end(), w.begin(), [](int x) { return x * x; }); Sorting: compare function Find, copy_if: predicate function Accumulate: binary function

  4. Combinators Currying, partial application: bind Combining algorithms v.erase(remove_if(v.begin(), v.end(), bind(logical_and<bool>(), v.end()); bind(greater<int>(), _1, -10), bind(less<int>(), _1, 10))),

  5. Future Channel for passing data (John Reppy, ML) Promise Future

  6. promise<string> prms; Thread A Thread B Promise Shared state Promise Page 7

  7. promise<string> prms; auto ftr = prms.get_future(); Thread A Thread B Future Promise Shared state Future Page 8

  8. promise<string> prms; auto ftr = prms.get_future(); thread th(&thFun, std::move(prms)); Thread A Thread B Future Promise Shared state Create thread Page 9

  9. promise<string> prms; auto ftr = prms.get_future(); thread th(&thFun, std::move(prms)); Thread A Thread B Future Promise Thread B prms.set_value( Hello from future ); Shared state Hello set_value Page 10

  10. promise<string> prms; auto ftr = prms.get_future(); thread th(&thFun, std::move(prms)); std::string str = ftr.get(); Thread A Thread B Future Promise Thread B prms.set_value( Hello from future ); Shared state Hello get Page 11

  11. Library Design Composability Orthogonality (Separation of concerns)

  12. Then Pattern Problem: Apply a function to a future future<string> ftr = async( ); string s = ftr.get(); // blocks? then continue to parse(s)

  13. Then Combinator future<string> ftr = async( ); string s = ftr.get(); // blocks? then parse(s) template<typename F> auto future::then(F&& func) -> future<decltype(func(*this))>; future<Tree> fTree = ftr.then([](future<string> fstr) { return parse(fstr.get()); // doesn t block }); Tree tree = fTree.get(); // blocks? Next combinator future<Tree> fTree = ftr.next(parse); Tree tree = fTree.get(); // blocks?

  14. Function Lifting future<string> fStr = future<Tree> fTree = fStr.next(parse); next lifts parse to act on futures vector<int> v = {1, 2, 3}; vector<int> w; w.resize(v.size()); transform(v.begin(), v.end(), w.begin(), square); transform lifts square to act on containers

  15. Type Constructor Unconstrained parametric polymorphism (universally quantified types) For all types T: template<class T> class future; template<class T> class vector; template<class T> class unique_ptr; A mapping of types: T -> future<T>

  16. The Functor Pattern Type constructor Function lifting: then, transform, (Haskell: fmap) T -> future<T> fuction<S(T)> -> function<future<S>(future<T>));

  17. Asynchronous Chaining Problem: Composing (chaining) async calls future<HANDLE> async_open(string &); future<Buffer> async_read(HANDLE fh); In principle, this is the result: future<future<Buffer>> ffBuf = async_open("foo").next(&async_read);

  18. Unwrap Collapse two levels of future async_open("foo.cpp").next(&async_read).unwrap().n ext(&async_process).unwrap(); Combination of next and unwrap called bind (Haskell: >>=, bind combines join with fmap) In C++, next (then) can be overloaded to serve as bind

  19. Lifting a value Usage: conditional asynchrony, recursion A future that is ready make_ready_future future<int> fint = make_ready_future<int>(42); int i = fint.get(); // doesn t block Analogously, for containers: vector<int> v = {42};

  20. Monad Pattern Functor pattern Type constructor Function lifting (then, next, transform) Collapsing (unwrap, concat) Value lifting (make_ready_future)

  21. Monad Pattern 2 Type constructor Value lifting: make_ready_future() bind: combination of .next(f).unwrap() [or an overload of next] Usage of the future monad pattern: Composing libraries of async functions

  22. Exceptions It s all in the wrist next (or bind) checks for exceptions and propagates them (without calling the continuation) At the end of the chain, recover from exception async_open("foo.cpp").next(&async_read).next(parse).r ecover(&on_error); Exception monad Implements short-circuiting Can be put on top of the future monad (monad transformers)

  23. Applicative Pattern Problem: Need N futures to proceed. Create a barrier, get all values, proceed. when_all: takes futures, returns future of finished futures Client gets, iterates, gets each, and proceeds with values Functional approach Apply a regular function of n argument to n futures. Lifting of n-ary functions when_all_done(futures).next(fn) Together with make_ready_future: applicative functor

  24. Monoid Pattern Problem: Wait for the first future to complete when_any: takes futures, returns a future of futures, at least one of them ready Client gets, iterates, checks is_ready, picks value. proceeds Functional approach The OR combinator (like addition?) Combines two futures into one Assoc.: (f1 OR f2) OR f3 = f1 OR (f2 OR f3) Neutral element: the never future never OR f = f = f OR never Defines a monoid

  25. Conclusions New patterns based on functional programming Functor Applicative Functor Monad Monoid Composability and orthogonality Result: Library of futures

More Related Content