SlideShare a Scribd company logo
The Present and The Future
of Functional Programming in C++
Alexander Granin
graninas@gmail.com
C++ Siberia 2019
Eric Niebler, C++ Siberia 2015
Ranges for the Standard Library
Eric Niebler, C++ Siberia 2015
Ranges for the Standard Library
Bartosz Milewski, С++ User Group 2014
Re-discovering monads in C++
Eric Niebler, C++ Siberia 2015
Ranges for the Standard Library
Bartosz Milewski, С++ User Group 2014
Re-discovering monads in C++
Ivan Čukić, C++ Siberia 2017
Atom heart monad (FRP in C++)
My talks about Functional Programming in C++
С++ User Group 2014
Functional and Declarative Design in C++
My talks about Functional Programming in C++
С++ User Group 2014
Functional and Declarative Design in C++
С++ Siberia 2015
Functional Microscope: Lenses in C++
My talks about Functional Programming in C++
С++ User Group 2014
Functional and Declarative Design in C++
С++ Siberia 2015
Functional Microscope: Lenses in C++
С++ Russia 2016
Functional “Life”: Parallel Cellular Automata and Comonads in C++
С++ User Group 2014
Functional and Declarative Design in C++
С++ Siberia 2015
Functional Microscope: Lenses in C++
С++ Russia 2016
Functional “Life”: Parallel Cellular Automata and Comonads in C++
С++ Russia 2018
Functional Approach to Software Transactional Memory in C++
My talks about Functional Programming in C++
struct Presentation
{
Philosophy of Functional Programming in C++
Elements of Functional Programming in C++
Functional Design, Patterns and Approaches In C++
Limitations of Functional Programming in C++
};
Philosophy
of Functional Programming in C++
What is Programming?
instructions, jumps, loops
-- unstructured programming
14
instructions, jumps, loops
sequence, selection, iteration
-- unstructured programming
-- structured programming
15
instructions, jumps, loops
sequence, selection, iteration
declaration, application, recursion
-- unstructured programming
-- functional programming
-- structured programming
16
class A {}
template<>
constexpr
#define
procedural programming
metaprogramming
functional programming
object-oriented programming
int main()
17
C++ Developer Evolution
C++ -> C++11/14 -> C++17/20Abstract C++ developer:
C++ Developer Evolution
C++ -> C++11/14 -> C++17/20
C++ -> Pain! -> C++11/14 -> My brain! -> C++17/20
Abstract C++ developer:
Real C++ developer:
C++ Developer Evolution
C++ -> C++11/14 -> C++17/20
C++ -> Pain! -> C++11/14 -> My brain! -> C++17/20
C++ -> WTF -> Go
Abstract C++ developer:
Real C++ developer:
Beginner C++ developer:
C++ Developer Evolution
C++ -> C++11/14 -> C++17/20
C++ -> Pain! -> C++11/14 -> My brain! -> C++17/20
C++ -> WTF -> Go
C++ -> C++11/14 -> Why?!! -> Haskell -> C++17/20
Abstract C++ developer:
Real C++ developer:
Beginner C++ developer:
Modern C++ developer:
C++ Developer Evolution
C++ -> C++11/14 -> C++17/20
C++ -> Pain! -> C++11/14 -> My brain! -> C++17/20
C++ -> WTF -> Go
C++ -> C++11/14 -> Why?!! -> Haskell -> C++17/20
C++ -> C++11/14 -> Uh-Oh -> Rust
Abstract C++ developer:
Real C++ developer:
Beginner C++ developer:
Modern C++ developer:
Tired C++ developer:
C++ Developer Evolution
C++ -> C++11/14 -> C++17/20
C++ -> Pain! -> C++11/14 -> My brain! -> C++17/20
C++ -> WTF -> Go
C++ -> C++11/14 -> Why?!! -> Haskell -> C++17/20
C++ -> C++11/14 -> Uh-Oh -> Rust
C++98 -> Please, leave me alone -> C++98
Abstract C++ developer:
Real C++ developer:
Beginner C++ developer:
Modern C++ developer:
Tired C++ developer:
Old School C++ developer:
C++ Developer Evolution
Functional programming in my C++?!!
25
Verbosity of imperative and OO code FP data types and constructs
algebraic data types, higher order functions, lambdas, closures
pattern-matching, currying, partial application
Functional programming in my C++?!!
26
Verbosity of imperative and OO code
Unsafety, bugs and lack or guarantees
FP data types and constructs
Reliable FP concepts, guarantees
purity, immutability, side effects control, type level programming
recursion, range-based iteration, monoids, functors, monads...
Functional programming in my C++?!!
27
Verbosity of imperative and OO code
Unsafety, bugs and lack or guarantees
Leaking and heavy abstractions
FP data types and constructs
Reliable FP concepts, guarantees
Declarative and functional design
domain specific languages, persistent data types
laziness, composition, combinators, first class functions
Functional programming in my C++?!!
28
Verbosity of imperative and OO code
Unsafety, bugs and lack or guarantees
Leaking and heavy abstractions
Complexity of multithreaded programs
FP data types and constructs
Reliable FP concepts, guarantees
Declarative and functional design
Functional approaches
functional reactive programming, software transactional memory,
async / par / future monad, automatic parallelism
Functional programming in my C++?!!
29
Elements
of Functional Programming in C++
𝝺ambdas
[](auto i) { return i + 1; }
i -> i + 1
i => i + 1
lambda i: i + 1
| i | -> i + 1
𝝺ambdas in C++
<>(int x, int y) -> int {return x + y;}
[|b|]() { return |b| -> set_text("World"); }
i => i + 1
[](auto i) { return i + 1; }
[]<>(auto i) { return i + 1; }
𝝺ambdas in C++
Idea of the feature
Standard issuing
Feature adoption
Feature improvements
== You are standing here ==
Feature improvements
<>(int x, int y) -> int {return x + y;}
[|b|]() { return |b| -> set_text("World"); }
i => i + 1
[](auto i) { return i + 1; }
[]<>(auto i) { return i + 1; }
𝝺ambdas in C++
Idea of the feature
Standard issuing
Feature adoption
Feature improvements
== You are standing here ==
Feature improvements
2011
...2000...
2014, 2017
...2011...
2020
2019
<>(int x, int y) -> int {return x + y;}
[|b|]() { return |b| -> set_text("World"); }
i => i + 1
[](auto i) { return i + 1; }
[]<>(auto i) { return i + 1; }
Idea of the feature
Pondering and thinking
Reference implementation
Discussions in Committee
Drafting in Standard
Implementation in compilers
Standard issuing
Feature adoption
Feature improvements
== You are standing here ==
Feature improvements
𝝺ambdas in C++
2011
...2000...
<>(int x, int y) -> int {return x + y;}
[|b|]() { return |b| -> set_text("World"); }
i => i + 1
[](auto i) { return i + 1; }
[]<>(auto i) { return i + 1; }
2014, 2017
...2011...
2008 - 2011
2006 - 2008
2020
2019
What is 𝝺ambda?
And who is
𝝺ambdaman? 36
“ 𝝺ambda is just an object with operator() overloaded”
std::vector<int> v {4, 2, 4};
struct Summator
{
int sum = 0;
void operator()(int i) {
sum += i;
}
};
Summator summator = std::for_each(v.begin(), v.end(), Summator());
std::cout << summator.sum; // 10
37
“ 𝝺ambda is an anonymous function”
std::vector<int> v {4, 2, 4};
auto sum = 0;
std::for_each(v.begin(), v.end(), [&sum](int i) { sum += i; });
std::cout << sum; // 10
38
“ 𝝺ambda is an universal combinator”
auto I = [](auto x) {
return x;
};
auto K = [](auto x) {
return [=](auto y) {
return x;
};
};
auto S = [](auto x) {
return [=](auto y) {
return [=](auto z) {
return (x(z))(y(z));
};
};
};
Ix = x
Kxy = x
Sxyz = xz(yz)
39
𝝺ambdas evolution
auto mul2 = [](int i) { return i * 2; }
auto mul2 = [](auto i) { return i * 2; }
constexpr auto mul2 = [](auto i) { return i * 2; }
auto mul2 = []<typename T>(T i) { return i * 2; }
auto mul2 = i => i * 2;
C++11
C++14
C++17
C++20
C++??
Lambda expressions
Polymorphic lambdas
Constexpr lambdas
“Familiar” syntax
Abbreviated syntax
40
Purity and Immutability
41
Pure Functional Programming in C++
42
Knuth’s Up-Arrow Notation
43
Knuth’s Up-Arrow Notation
44
Knuth’s Up-Arrow Notation
45
Knuth’s Up-Arrow Notation
46
47
https://www.youtube.com/watch?v=PJwd4JLYJJY
constexpr ALL the Things!
Recursive constexpr pow() function
using UInt = uint64_t;
constexpr UInt pow(UInt a, UInt b) {
return b == 0
? 1
: a * pow(a, b - 1);
}
48
Recursive constexpr tower() function
using UInt = uint64_t;
constexpr UInt pow(UInt a, UInt b) {
return b == 0
? 1
: a * pow(a, b - 1);
}
constexpr UInt tower(UInt a, UInt b) {
return b == 0
? throw std::invalid_argument("b == 0")
: b == 1
? a
: pow(a, tower(a, b - 1));
}
49
Throwing exception at compile time?
using UInt = uint64_t;
constexpr UInt pow(UInt a, UInt b) {
return b == 0
? 1
: a * pow(a, b - 1);
}
constexpr UInt tower(UInt a, UInt b) {
return b == 0
? throw std::invalid_argument("b == 0")
: b == 1
? a
: pow(a, tower(a, b - 1));
}
50
Recurrent formula
51
constexpr UInt arr_impl(bool brackets_rec, UInt cnt, UInt a, UInt n, UInt b)
{
return brackets_rec
? (cnt == 0 ? ... ... ...) // recursion by brackets
: (n == 1
? pow(a, b)
: n == 2
? tower(a, b)
: arr_impl(true, b - 1, a, n - 1, a)); // recursion by arrows
}
Double recursion constexpr arr_impl() function
52
constexpr UInt arr(UInt a, UInt n, UInt b)
{
return arr_impl(false, 0, a, n, b);
}
constexpr UInt x1 = arr(3, 2, 3); // Compile-time evaluated
UInt x2 = arr(3, 2, 3); // Has to be compile-time evaluated
// 3 ↑↑ 3 = 7625597484987
Evaluation
53
Pure Template Functional Programming in C++
54
Template Pow “function”
template <UInt A, UInt N>
struct Pow
{
static constexpr UInt value = A * Pow<A, N - 1>::value;
};
template <UInt A>
struct Pow<A, 0>
{
static constexpr UInt value = 1;
};
55
Template Pow “function”
template <UInt A, UInt N>
struct Pow
{
static constexpr UInt value = A * Pow<A, N - 1>::value;
};
template <UInt A>
struct Pow<A, 0>
{
static constexpr UInt value = 1;
};
56
“Pat n c i g”
“Rec on”
Template Tower “function”
template <UInt A, UInt B>
struct Tower
{
static constexpr UInt value = Pow<A, Tower<A, B - 1>::value>::value;
};
template <UInt A>
struct Tower<A, 1>
{
static constexpr UInt value = A;
};
57
Template ArrImpl “function”
template <bool brackets_rec, UInt C, UInt A, UInt S, UInt B>
struct ArrImpl
{
static constexpr UInt value = 1;
};
template <UInt C, UInt A, UInt S, UInt B>
struct ArrImpl<true, C, A, S, B>
{
static constexpr UInt value
= ArrImpl<false, 0, A,
ArrImpl<true, C - 1, A, S, B>::value,
S>::value;
};
... // More template code 58
“Evaluation”
template <UInt A, UInt S, UInt B>
struct Arr
{
static constexpr UInt value = ArrImpl<false, 0, A, S, B>::value;
};
auto result = Arr<3, 2, 3>::value; // 3 ↑↑ 3 = 7625597484987
59
Template ⇨ constexpr = 👍
template <UInt A, UInt S, UInt B>
struct Arr
{
static constexpr UInt value = arr_impl(false, 0, A, S, B);
};
60
Constexpr ⇨ template = ☠
template <UInt A, UInt S, UInt B>
struct Arr
{
static constexpr UInt value = arr_impl(false, 0, A, S, B);
};
// Won’t compile:
constexpr UInt arr(UInt a, UInt s, UInt b)
{
return ArrImpl<false, 0, a, s, b>::value;
}
61
Constexpr ⇨ template = ☠
template <UInt A, UInt S, UInt B>
struct Arr
{
static constexpr UInt value = arr_impl(false, 0, A, S, B);
};
// Won’t compile:
constexpr UInt arr(UInt a, UInt s, UInt b)
{
return ArrImpl<false, 0, a, s, b>::value;
}
62
Dep
n y e ??
template <UInt A, UInt S, UInt B>
struct Arr
{
static constexpr UInt value = arr_impl(false, 0, A, S, B);
};
template <UInt A, UInt S, UInt B>
constexpr UInt arr()
{
return ArrImpl<false, 0, A, S, B>::value;
}
Template constexpr!
63
* * *
64
65https://www.youtube.com/watch?v=iWDjoD3MdXs
expected<T, E>: Proposal P0323R2
expected<double, error_condition>
safe_divide(double i, double j)
{
if (j == 0)
{
return make_unexpected(arithmetic_error::divide_by_zero);
}
else
{
return i / j;
}
}
66
template <typename T, typename E>
using Expected = std::variant<T, E>;
enum class Errors {
ZeroTowerError = 0,
ZeroDivisionError = 1
};
using UInt = uint64_t;
using SafeInt = Expected<UInt, Errors>;
constexpr SafeInt make_pure (const UInt& v) { return { v }; }
constexpr SafeInt make_error(const Errors& e) { return { e }; }
Custom Expected<T, E>
67
Sum p i g d::va t
template <typename T, typename E>
using Expected = std::variant<T, E>;
enum class Errors {
ZeroTowerError = 0,
ZeroDivisionError = 1
};
using UInt = uint64_t;
using SafeInt = Expected<UInt, Errors>;
constexpr SafeInt make_pure (const UInt& v) { return { v }; }
constexpr SafeInt make_error(const Errors& e) { return { e }; }
Custom Expected<T, E>
68
Sup t e r & al
template <typename T, typename E>
using Expected = std::variant<T, E>;
enum class Errors {
ZeroTowerError = 0,
ZeroDivisionError = 1
};
using UInt = uint64_t;
using SafeInt = Expected<UInt, Errors>;
constexpr SafeInt make_pure (const UInt& v) { return { v }; }
constexpr SafeInt make_error(const Errors& e) { return { e }; }
Custom Expected<T, E>
69
Con r r
std::variant<UInt, Errors> val = make_pure(10);
UInt result = std::holds_alternative<UInt>(val)
? std::get<UInt>(val)
: throw std::runtime_error("Error got.");
Extracting values of variant<>
70
Pattern Matching?
struct SafeIntVisitor
{
void operator()(const UInt& i) { cout << "Result: " << i; }
void operator()(const Errors& e) { cout << "Error: " << e; }
};
std::visit(SafeIntVisitor(), val);
inspect (val)
{
<UInt> i: cout << "Result: " << i;
<Errors> e: cout << "Error: " << e;
};
71
Vis g d::va t
Pattern Matching!
struct SafeIntVisitor
{
void operator()(const UInt& i) { cout << "Result: " << i; }
void operator()(const Errors& e) { cout << "Error: " << e; }
};
std::visit(SafeIntVisitor(), val);
inspect (val)
{
<UInt> i: cout << "Result: " << i;
<Errors> e: cout << "Error: " << e;
};
72
Pat n c i g
Pro l P1260R0
Object-oriented programming is an exceptionally bad
idea which could only have originated in California.
-- Edsger Dijkstra
73
Functional Design,
Patterns and Approaches in C++
Monadic error handling with Expected<T, E>
template <typename T, typename E>
using Expected = std::variant<T, E>;
enum class Errors {
ZeroTowerError = 0,
ZeroDivisionError = 1
};
using UInt = uint64_t;
using SafeInt = Expected<UInt, Errors>;
constexpr SafeInt make_pure (const UInt& v) { return { v }; }
constexpr SafeInt make_error(const Errors& e) { return { e }; }
75
UInt pow(UInt a, UInt n) { ... }
UInt tower(UInt a, UInt b) {
return b == 0
? throw std::invalid_argument("b == 0")
: b == 1
? a
: pow(a, tower(a, b - 1));
}
Unsafe tower() function
76
UInt pow(UInt a, UInt n) { ... }
SafeInt safe_tower(UInt a, UInt b) {
return b == 0
? make_error(Errors::ZeroTowerError)
: b == 1
? a
: pow(a, tower(a, b - 1));
}
safe_tower() function
77
UInt pow(UInt a, UInt n) { ... }
SafeInt safe_tower(UInt a, UInt b) {
return b == 0
? make_error(Errors::ZeroTowerError)
: b == 1
? a
: pow(a, tower(a, b - 1));
}
safe_tower() function
78
UInt pow(UInt a, UInt n) { ... }
SafeInt safe_tower(UInt a, UInt b) {
return b == 0
? make_error(Errors::ZeroTowerError)
: b == 1
? a
: pow(a, tower(a, b - 1));
}
safe_tower() function
79
UInt pow(UInt a, UInt n) { ... }
SafeInt safe_tower(UInt a, UInt b) {
return b == 0
? make_error(Errors::ZeroTowerError)
: b == 1
? make_pure(a)
: make_pure(pow(a, tower(a, b - 1)));
}
safe_tower() function
80
UInt pow(UInt a, UInt n) { ... }
SafeInt safe_tower(UInt a, UInt b) {
return b == 0
? make_error(Errors::ZeroTowerError)
: b == 1
? make_pure(a)
: make_pure(pow(a, tower(a, b - 1)));
}
safe_tower() function
81
UInt pow(UInt a, UInt n) { ... }
SafeInt safe_tower(UInt a, UInt b) {
return b == 0
? make_error(Errors::ZeroTowerError)
: b == 1
? make_pure(a)
: make_pure(pow(a, tower(a, b - 1)));
}
safe_tower() function
82
UInt pow(UInt a, UInt n) { ... }
SafeInt safe_tower(UInt a, UInt b) {
return b == 0
? make_error(Errors::ZeroTowerError)
: b == 1
? make_pure(a)
: make_pure(pow(a, safe_tower(a, b - 1)));
}
safe_tower() function
83
UInt pow(UInt a, UInt n) { ... }
SafeInt safe_tower(UInt a, UInt b) {
return b == 0
? make_error(Errors::ZeroTowerError)
: b == 1
? make_pure(a)
: make_pure(pow(a, safe_tower(a, b - 1)));
}
safe_tower() function
84
UInt pow(UInt a, UInt n) { ... }
SafeInt safe_tower(UInt a, UInt b) {
return b == 0
? make_error(Errors::ZeroTowerError)
: b == 1
? make_pure(a)
: make_pure(pow(a, safe_tower(a, b - 1)));
}
safe_tower() function
85
UInt pow(UInt a, UInt n) { ... }
SafeInt safe_tower(UInt a, UInt b) {
return b == 0
? make_error(Errors::ZeroTowerError)
: b == 1
? make_pure(a)
: mbind(safe_tower(a, b - 1),
[=](UInt v) { return make_pure(pow(a, v)); }
);
}
Monadic binding*
86
* Almost
UInt pow(UInt a, UInt n) { ... }
SafeInt safe_tower(UInt a, UInt b) {
return b == 0
? make_error(Errors::ZeroTowerError)
: b == 1
? make_pure(a)
: mbind(safe_tower(a, b - 1),
[=](UInt v) { return make_pure(pow(a, v)); }
);
}
Monadic binding*
87
* Almost
SafeInt mbind (SafeInt, Func<SafeInt, UInt>)
mbind :: SafeInt -> (UInt -> SafeInt) -> SafeInt
template <typename T, typename E, typename Lambda>
SafeInt mbind(SafeInt safe_val, Lambda lambda)
{
return std::holds_alternative<E>(safe_val)
? safe_val
: lambda(std::get<T>(safe_val));
}
mbind() function
88
auto mul10 = [](UInt i) { return make_pure(i * 10); };
SafeInt v1 = safe_tower(2, 0);
SafeInt v2 = mbind(v1, mul10);
std::visit(SafeIntVisitor(), v1); // error : 0
std::visit(SafeIntVisitor(), v2); // error : 0
Monadic chaining*, error path
89
* Almost
auto mul10 = [](UInt i) { return make_pure(i * 10); };
SafeInt v1 = safe_tower(2, 3);
SafeInt v2 = mbind(
mbind(v1, mul10),
mul10
);
std::visit(SafeIntVisitor(), v1); // result: 16
std::visit(SafeIntVisitor(), v2); // result: 1600
Monadic chaining*, success path
90
* Almost
auto mul10 = [](UInt i) { return make_pure(i * 10); };
SafeInt v1 = safe_tower(2, 3);
SafeInt v2 = mbind(
mbind(v1, mul10),
mul10
);
SafeInt v2 = do {
UInt i1 <- safe_tower(2, 3);
UInt i2 <- mul10(i1);
return mul10(i2);
}
Monadic chaining*, do-notation dream
91
* Almost
m i d
d e n “<-”
expected<int, Errors> safe_calculate(int a, int b) {
do {
UInt v <- safe_tower(a, b);
int r <- safe_divide(v, b);
return r;
}
}
Do-notation dreams
expected<int, Errors> safe_calculate(int a, int b) {
UInt v = try safe_tower(a, b);
int r = try safe_divide(v, b);
return r;
}
92
Has l-li “do”
Pro l P0650R1
“C++ Mon In e f ”
MONADS
It’s what we like memes to be about
93
expected<int, Errors> safe_calculate(int a, int b) {
do {
UInt v <- safe_tower(a, b);
int r <- safe_divide(v, b);
return r;
}
}
Monads everywhere: expected<>
94
mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E>
optional<int> same_age_persons_count(int personId) {
do {
Person p <- get(personId);
Persons ps <- find( [=](Person x){ return x.age == p.age; } );
return ps.size();
}
}
Monads everywhere: optional<>
95
mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E>
mbind :: optional<A> -> (A -> optional<B>) -> optional<B>
future<int> calculate(int a, int b) {
do {
int x <- heavy_calc(a);
int y <- heavy_calc(b);
return heavy_calc(x + y);
}
}
Monads everywhere: future<>
96
mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E>
mbind :: optional<A> -> (A -> optional<B>) -> optional<B>
mbind :: future<A> -> (A -> future<B>) -> future<B>
async<Result> request_person(int personId) {
do {
auto person <- request_person(personId);
auto confs <- request_conferences(personId);
bool saved1 <- save(person);
bool saved2 <- save(confs);
return {saved1 && saved2, person, confs};
}
}
Monads everywhere: async<> (coroutines?)
97
mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E>
mbind :: optional<A> -> (A -> optional<B>) -> optional<B>
mbind :: future<A> -> (A -> future<B>) -> future<B>
mbind :: async<A> -> (A -> async<B>) -> async<B>
parser<Person> person() {
do {
_ <- many(space);
first_name <- name();
_ <- many(space);
last_name <- name();
return {first_name, last_name};
}
}
Monads everywhere: parser<>
98
mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E>
mbind :: optional<A> -> (A -> optional<B>) -> optional<B>
mbind :: future<A> -> (A -> future<B>) -> future<B>
mbind :: async<A> -> (A -> async<B>) -> async<B>
mbind :: parser<A> -> (A -> parser<B>) -> parser<B>
* * *
99
100
https://www.youtube.com/watch?v=sPhpelUfu8Q
Postmodern immutable data structures
101
102
https://www.youtube.com/watch?v=mFUXNMfaciE
103
auto triples =
for_each(iota(1), [](int z) {
return for_each(iota(1, z+1), [=](int x) {
return for_each(iota(x, z+1), [=](int y) {
return yield_if(x*x + y*y == z*z,
make_tuple(x, y, z));
});
});
});
Pythagorean Triples in Ranges
104
auto triples =
for_each(iota(1), [](int z) {
return for_each(iota(1, z+1), [=](int x) {
return for_each(iota(x, z+1), [=](int y) {
return yield_if(x*x + y*y == z*z,
make_tuple(x, y, z));
});
});
});
Pythagorean Triples in Ranges
105
auto triples =
for_each(iota(1), [](int z) {
return for_each(iota(1, z+1), [=](int x) {
return for_each(iota(x, z+1), [=](int y) {
return yield_if(x*x + y*y == z*z,
make_tuple(x, y, z));
});
});
});
for(auto triple : triples | view::take(10)) {
cout << '('
<< get<0>(triple) << ','
<< get<1>(triple) << ','
<< get<2>(triple) << ')' << 'n';
}
Pythagorean Triples in Ranges
Output:
(3,4,5)
(6,8,10)
(5,12,13)
(9,12,15)
(8,15,17)
(12,16,20)
(7,24,25)
(15,20,25)
(10,24,26)
(20,21,29)
106
Pythagorean Triples in Ranges, reformatted
auto triples =
for_each(iota(1), [] (int z) { return
for_each(iota(1, z+1), [=](int x) { return
for_each(iota(x, z+1), [=](int y) { return
yield_if(x*x + y*y == z*z, make_tuple(x, y, z));
}); }); });
107
Looks familiar...
auto triples =
for_each(iota(1), [] (int z) { return
for_each(iota(1, z+1), [=](int x) { return
for_each(iota(x, z+1), [=](int y) { return
yield_if(x*x + y*y == z*z, make_tuple(x, y, z));
}); }); });
iota :: list<int>
for_each :: list<int> -> (int -> list<int>) -> list<int>
108
for_each → mbind...
auto triples =
mbind(iota(1), [] (int z) { return
mbind(iota(1, z+1), [=](int x) { return
mbind(iota(x, z+1), [=](int y) { return
yield_if(x*x + y*y == z*z, make_tuple(x, y, z));
}); }); });
iota :: list<int>
for_each :: list<int> -> (int -> list<int>) -> list<int>
mbind :: list<int> -> (int -> list<int>) -> list<int>
109
Monads, again??
auto triples =
mbind(iota(1), [] (int z) { return
mbind(iota(1, z+1), [=](int x) { return
mbind(iota(x, z+1), [=](int y) { return
yield_if(x*x + y*y == z*z, make_tuple(x, y, z));
}); }); });
auto triples =
do {
int z <- iota(1);
int x <- iota(1, z+1);
int y <- iota(x, z+1);
guard (x*x + y*y == z*z);
return make_tuple(x, y, z);
}
110
auto triples =
mbind(iota(1), [] (int z) { return
mbind(iota(1, z+1), [=](int x) { return
mbind(iota(x, z+1), [=](int y) { return
yield_if(x*x + y*y == z*z, make_tuple(x, y, z));
}); }); });
auto triples =
do {
int z <- iota(1);
int x <- iota(1, z+1);
int y <- iota(x, z+1);
guard (x*x + y*y == z*z);
return make_tuple(x, y, z);
}
Monadic Pythagorean Triples in Haskell
triples = do
z <- [1..]
x <- [1..z]
y <- [x..z]
guard (x*x + y*y == z*z)
pure (x, y, z)
111
It’s inevitable. This is terrifying.
mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E> // error handling
mbind :: optional<A> -> (A -> optional<B>) -> optional<B> // absent values
mbind :: future<A> -> (A -> future<B>) -> future<B> // parallelism
mbind :: async<A> -> (A -> async<B>) -> async<B> // callback hell
elimination
mbind :: parser<A> -> (A -> parser<B>) -> parser<B> // parsing
mbind :: list<A> -> (A -> list<B>) -> list<B> // combinatorics
(kind of)
mbind :: reader<A> -> (A -> reader<B>) -> reader<B> // environment data
mbind :: writer<A> -> (A -> writer<B>) -> writer<B> // write-only data
mbind :: state<A> -> (A -> state<B>) -> state<B> // monadic state
mbind :: io<A> -> (A -> io<B>) -> io<B> // effects control
112
for(auto triple : triples | view::take(10)) {
cout << '('
<< get<0>(triple) << ','
<< get<1>(triple) << ','
<< get<2>(triple) << ')' << 'n';
}
Functional composition with ranges
Output:
(3,4,5)
(6,8,10)
(5,12,13)
(9,12,15)
(8,15,17)
(12,16,20)
(7,24,25)
(15,20,25)
(10,24,26)
(20,21,29)
113
for(auto triple : triples | view::take(10)
| view::transform(mul10_middle)) {
cout << '('
<< get<0>(triple) << ','
<< get<1>(triple) << ','
<< get<2>(triple) << ')' << 'n';
}
auto mul10_middle = [](const tuple<int, int, int>& t) {
const auto& [x, y, z] = t;
return make_tuple(x, y * 10, z);
};
Functional composition with ranges
Output:
(3,40,5)
(6,80,10)
(5,120,13)
(9,120,15)
(8,150,17)
(12,160,20)
(7,240,25)
(15,200,25)
(10,240,26)
(20,210,29)
114
for(auto triple : triples | view::take(10)
| view::transform(mul10_middle)
| view::reverse) {
cout << '('
<< get<0>(triple) << ','
<< get<1>(triple) << ','
<< get<2>(triple) << ')' << 'n';
}
auto mul10_middle = [](const tuple<int, int, int>& t) {
const auto& [x, y, z] = t;
return make_tuple(x, y * 10, z);
};
Functional composition with ranges
Output:
(20,210,29)
(10,240,26)
(15,200,25)
(7,240,25)
(12,160,20)
(8,150,17)
(9,120,15)
(5,120,13)
(6,80,10)
(3,40,5)
Limitations
of Functional Programming in C++
116
“Problems” of Functional Programming in C++
● Compilation time
● Hard debugging
● Performance
117
Issues of Functional Programming in C++
● Absence of currying
● Dangerous closures
● Lambdas are verbose
● Tuple is extremely verbose
118
Real Problems of Functional Programming in C++
● Poor type system
○ No real Algebraic Data Types
○ No real function type
○ Lambdas have unique types
○ No real pattern matching (yet)
■ Won’t be expression??
○ Type inference is weak
● Composition of functions is complicated
● No native support of monads (in 2019)
119
Real Problems of Functional Programming in C++
C++
● Poor type system
○ No real Algebraic Data Types
○ No real function type
○ Lambdas have unique types
○ No real pattern matching (yet)
■ Won’t be expression??
○ Type inference is weak
● Composition of functions is complicated
● No native support of monads (in 2019)
Prediction for high-level C++
time
High-level C++
adoption
2020
New high-level features
2023
120
121
GitHub List: Functional Programming in C++
https://github.com/graninas/cpp_functional_programming👉
● Books
● Articles
● Papers
● Talks
● QA
● Libraries
● Showcase projects
122
Thanks for watching!
Let’s talk?
C++ Siberia 2019
Alexander Granin
graninas@gmail.com
???
125

More Related Content

What's hot

PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...
Andrey Karpov
 
[C++ Korea] Effective Modern C++ Study, Item 11 - 13
[C++ Korea] Effective Modern C++ Study, Item 11 - 13[C++ Korea] Effective Modern C++ Study, Item 11 - 13
[C++ Korea] Effective Modern C++ Study, Item 11 - 13
Chris Ohk
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
corehard_by
 
CBSE Question Paper Computer Science with C++ 2011
CBSE Question Paper Computer Science with C++ 2011CBSE Question Paper Computer Science with C++ 2011
CBSE Question Paper Computer Science with C++ 2011
Deepak Singh
 
C and C++ Industrial Training Jalandhar
C and C++ Industrial Training JalandharC and C++ Industrial Training Jalandhar
C and C++ Industrial Training Jalandhar
Dreamtech Labs
 
UGC-NET, GATE and all IT Companies Interview C++ Solved Questions PART - 2
UGC-NET, GATE and all IT Companies Interview C++ Solved Questions PART - 2UGC-NET, GATE and all IT Companies Interview C++ Solved Questions PART - 2
UGC-NET, GATE and all IT Companies Interview C++ Solved Questions PART - 2
Knowledge Center Computer
 
Aspect-Oriented Technologies
Aspect-Oriented TechnologiesAspect-Oriented Technologies
Aspect-Oriented Technologies
Esteban Abait
 
Computer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paperComputer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paperDeepak Singh
 
Part - 2 Cpp programming Solved MCQ
Part - 2  Cpp programming Solved MCQ Part - 2  Cpp programming Solved MCQ
Part - 2 Cpp programming Solved MCQ
Knowledge Center Computer
 
C++ via C#
C++ via C#C++ via C#
C++ via C#
Egor Bogatov
 
Polymorphismupload
PolymorphismuploadPolymorphismupload
Polymorphismupload
Mukhtar_Hunzai
 
C introduction by piyushkumar
C introduction by piyushkumarC introduction by piyushkumar
C introduction by piyushkumar
piyush Kumar Sharma
 
Egor Bogatov - .NET Core intrinsics and other micro-optimizations
Egor Bogatov - .NET Core intrinsics and other micro-optimizationsEgor Bogatov - .NET Core intrinsics and other micro-optimizations
Egor Bogatov - .NET Core intrinsics and other micro-optimizations
Egor Bogatov
 
Technical aptitude Test 1 CSE
Technical aptitude Test 1 CSETechnical aptitude Test 1 CSE
Technical aptitude Test 1 CSE
Sujata Regoti
 
Technical aptitude test 2 CSE
Technical aptitude test 2 CSETechnical aptitude test 2 CSE
Technical aptitude test 2 CSE
Sujata Regoti
 
CBSE Grade12, Computer Science, Sample Question Paper
CBSE Grade12, Computer Science, Sample Question PaperCBSE Grade12, Computer Science, Sample Question Paper
CBSE Grade12, Computer Science, Sample Question Paper
Malathi Senthil
 
Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009Deepak Singh
 
Develop Embedded Software Module-Session 3
Develop Embedded Software Module-Session 3Develop Embedded Software Module-Session 3
Develop Embedded Software Module-Session 3
Naveen Kumar
 
Idiomatic C++
Idiomatic C++Idiomatic C++
Idiomatic C++
Federico Ficarelli
 
C++
C++C++

What's hot (20)

PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...PVS-Studio team experience: checking various open source projects, or mistake...
PVS-Studio team experience: checking various open source projects, or mistake...
 
[C++ Korea] Effective Modern C++ Study, Item 11 - 13
[C++ Korea] Effective Modern C++ Study, Item 11 - 13[C++ Korea] Effective Modern C++ Study, Item 11 - 13
[C++ Korea] Effective Modern C++ Study, Item 11 - 13
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
 
CBSE Question Paper Computer Science with C++ 2011
CBSE Question Paper Computer Science with C++ 2011CBSE Question Paper Computer Science with C++ 2011
CBSE Question Paper Computer Science with C++ 2011
 
C and C++ Industrial Training Jalandhar
C and C++ Industrial Training JalandharC and C++ Industrial Training Jalandhar
C and C++ Industrial Training Jalandhar
 
UGC-NET, GATE and all IT Companies Interview C++ Solved Questions PART - 2
UGC-NET, GATE and all IT Companies Interview C++ Solved Questions PART - 2UGC-NET, GATE and all IT Companies Interview C++ Solved Questions PART - 2
UGC-NET, GATE and all IT Companies Interview C++ Solved Questions PART - 2
 
Aspect-Oriented Technologies
Aspect-Oriented TechnologiesAspect-Oriented Technologies
Aspect-Oriented Technologies
 
Computer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paperComputer science-2010-cbse-question-paper
Computer science-2010-cbse-question-paper
 
Part - 2 Cpp programming Solved MCQ
Part - 2  Cpp programming Solved MCQ Part - 2  Cpp programming Solved MCQ
Part - 2 Cpp programming Solved MCQ
 
C++ via C#
C++ via C#C++ via C#
C++ via C#
 
Polymorphismupload
PolymorphismuploadPolymorphismupload
Polymorphismupload
 
C introduction by piyushkumar
C introduction by piyushkumarC introduction by piyushkumar
C introduction by piyushkumar
 
Egor Bogatov - .NET Core intrinsics and other micro-optimizations
Egor Bogatov - .NET Core intrinsics and other micro-optimizationsEgor Bogatov - .NET Core intrinsics and other micro-optimizations
Egor Bogatov - .NET Core intrinsics and other micro-optimizations
 
Technical aptitude Test 1 CSE
Technical aptitude Test 1 CSETechnical aptitude Test 1 CSE
Technical aptitude Test 1 CSE
 
Technical aptitude test 2 CSE
Technical aptitude test 2 CSETechnical aptitude test 2 CSE
Technical aptitude test 2 CSE
 
CBSE Grade12, Computer Science, Sample Question Paper
CBSE Grade12, Computer Science, Sample Question PaperCBSE Grade12, Computer Science, Sample Question Paper
CBSE Grade12, Computer Science, Sample Question Paper
 
Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009Cbse question-paper-computer-science-2009
Cbse question-paper-computer-science-2009
 
Develop Embedded Software Module-Session 3
Develop Embedded Software Module-Session 3Develop Embedded Software Module-Session 3
Develop Embedded Software Module-Session 3
 
Idiomatic C++
Idiomatic C++Idiomatic C++
Idiomatic C++
 
C++
C++C++
C++
 

Similar to The Present and The Future of Functional Programming in C++

The present and the future of functional programming in c++
The present and the future of functional programming in c++The present and the future of functional programming in c++
The present and the future of functional programming in c++
Alexander Granin
 
Novidades do c# 7 e 8
Novidades do c# 7 e 8Novidades do c# 7 e 8
Novidades do c# 7 e 8
Giovanni Bassi
 
Effective Object Oriented Design in Cpp
Effective Object Oriented Design in CppEffective Object Oriented Design in Cpp
Effective Object Oriented Design in Cpp
CodeOps Technologies LLP
 
C++ in the 21st Century
C++ in the 21st CenturyC++ in the 21st Century
C++ in the 21st Century
bittorrentinc
 
Return of c++
Return of c++Return of c++
Return of c++
Yongwei Wu
 
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
tdc-globalcode
 
CAP444-Unit-3-Polymorphism.pptx
CAP444-Unit-3-Polymorphism.pptxCAP444-Unit-3-Polymorphism.pptx
CAP444-Unit-3-Polymorphism.pptx
Surajgroupsvideo
 
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Value Objects, Full Throttle (to be updated for spring TC39 meetings)Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Brendan Eich
 
Design Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on ExamplesDesign Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on Examples
Ganesh Samarthyam
 
C++ functions
C++ functionsC++ functions
C++ functions
Mayank Jain
 
C++ Overview PPT
C++ Overview PPTC++ Overview PPT
C++ Overview PPT
Thooyavan Venkatachalam
 
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015
Windows Developer
 
High performance web programming with C++14
High performance web programming with C++14High performance web programming with C++14
High performance web programming with C++14
Matthieu Garrigues
 
C++ Programming
C++ ProgrammingC++ Programming
Presentation on C++ Programming Language
Presentation on C++ Programming LanguagePresentation on C++ Programming Language
Presentation on C++ Programming Language
satvirsandhu9
 
C++ Functions
C++ FunctionsC++ Functions
C++ Functions
sathish sak
 
Rcpp: Seemless R and C++
Rcpp: Seemless R and C++Rcpp: Seemless R and C++
Rcpp: Seemless R and C++Romain Francois
 
C++ functions presentation by DHEERAJ KATARIA
C++ functions presentation by DHEERAJ KATARIAC++ functions presentation by DHEERAJ KATARIA
C++ functions presentation by DHEERAJ KATARIA
Dheeraj Kataria
 
C++ Programming
C++ ProgrammingC++ Programming
C++ Programming
Rounak Samdadia
 
Programming For Engineers Functions - Part #1.pptx
Programming For Engineers Functions - Part #1.pptxProgramming For Engineers Functions - Part #1.pptx
Programming For Engineers Functions - Part #1.pptx
NoorAntakia
 

Similar to The Present and The Future of Functional Programming in C++ (20)

The present and the future of functional programming in c++
The present and the future of functional programming in c++The present and the future of functional programming in c++
The present and the future of functional programming in c++
 
Novidades do c# 7 e 8
Novidades do c# 7 e 8Novidades do c# 7 e 8
Novidades do c# 7 e 8
 
Effective Object Oriented Design in Cpp
Effective Object Oriented Design in CppEffective Object Oriented Design in Cpp
Effective Object Oriented Design in Cpp
 
C++ in the 21st Century
C++ in the 21st CenturyC++ in the 21st Century
C++ in the 21st Century
 
Return of c++
Return of c++Return of c++
Return of c++
 
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
 
CAP444-Unit-3-Polymorphism.pptx
CAP444-Unit-3-Polymorphism.pptxCAP444-Unit-3-Polymorphism.pptx
CAP444-Unit-3-Polymorphism.pptx
 
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Value Objects, Full Throttle (to be updated for spring TC39 meetings)Value Objects, Full Throttle (to be updated for spring TC39 meetings)
Value Objects, Full Throttle (to be updated for spring TC39 meetings)
 
Design Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on ExamplesDesign Patterns - Compiler Case Study - Hands-on Examples
Design Patterns - Compiler Case Study - Hands-on Examples
 
C++ functions
C++ functionsC++ functions
C++ functions
 
C++ Overview PPT
C++ Overview PPTC++ Overview PPT
C++ Overview PPT
 
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015
Build 2016 - B880 - Top 6 Reasons to Move Your C++ Code to Visual Studio 2015
 
High performance web programming with C++14
High performance web programming with C++14High performance web programming with C++14
High performance web programming with C++14
 
C++ Programming
C++ ProgrammingC++ Programming
C++ Programming
 
Presentation on C++ Programming Language
Presentation on C++ Programming LanguagePresentation on C++ Programming Language
Presentation on C++ Programming Language
 
C++ Functions
C++ FunctionsC++ Functions
C++ Functions
 
Rcpp: Seemless R and C++
Rcpp: Seemless R and C++Rcpp: Seemless R and C++
Rcpp: Seemless R and C++
 
C++ functions presentation by DHEERAJ KATARIA
C++ functions presentation by DHEERAJ KATARIAC++ functions presentation by DHEERAJ KATARIA
C++ functions presentation by DHEERAJ KATARIA
 
C++ Programming
C++ ProgrammingC++ Programming
C++ Programming
 
Programming For Engineers Functions - Part #1.pptx
Programming For Engineers Functions - Part #1.pptxProgramming For Engineers Functions - Part #1.pptx
Programming For Engineers Functions - Part #1.pptx
 

More from Alexander Granin

Concurrent applications with free monads and stm
Concurrent applications with free monads and stmConcurrent applications with free monads and stm
Concurrent applications with free monads and stm
Alexander Granin
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fp
Alexander Granin
 
Final tagless vs free monad
Final tagless vs free monadFinal tagless vs free monad
Final tagless vs free monad
Alexander Granin
 
О разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop developmentО разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop development
Alexander Granin
 
Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...
Alexander Granin
 
Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...
Alexander Granin
 
Закон Деметры / Demetra's law
Закон Деметры / Demetra's lawЗакон Деметры / Demetra's law
Закон Деметры / Demetra's law
Alexander Granin
 
Design of big applications in FP
Design of big applications in FPDesign of big applications in FP
Design of big applications in FP
Alexander Granin
 
GitHub - зеркало разработчика
GitHub - зеркало разработчикаGitHub - зеркало разработчика
GitHub - зеркало разработчика
Alexander Granin
 
Functional programming in C++ LambdaNsk
Functional programming in C++ LambdaNskFunctional programming in C++ LambdaNsk
Functional programming in C++ LambdaNsk
Alexander Granin
 
Transition graph using free monads and existentials
Transition graph using free monads and existentialsTransition graph using free monads and existentials
Transition graph using free monads and existentials
Alexander Granin
 
Software transactional memory. pure functional approach
Software transactional memory. pure functional approachSoftware transactional memory. pure functional approach
Software transactional memory. pure functional approach
Alexander Granin
 
Вы не понимаете ФП / You don't understand FP
Вы не понимаете ФП / You don't understand FPВы не понимаете ФП / You don't understand FP
Вы не понимаете ФП / You don't understand FP
Alexander Granin
 
Functional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonadsFunctional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonads
Alexander Granin
 
Functional microscope - Lenses in C++
Functional microscope - Lenses in C++Functional microscope - Lenses in C++
Functional microscope - Lenses in C++
Alexander Granin
 
Дизайн больших приложений в ФП
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФП
Alexander Granin
 
Линзы - комбинаторная манипуляция данными
Линзы - комбинаторная манипуляция даннымиЛинзы - комбинаторная манипуляция данными
Линзы - комбинаторная манипуляция данными
Alexander Granin
 
Линзы - комбинаторная манипуляция данными (Dev2Dev)
Линзы - комбинаторная манипуляция данными (Dev2Dev)Линзы - комбинаторная манипуляция данными (Dev2Dev)
Линзы - комбинаторная манипуляция данными (Dev2Dev)
Alexander Granin
 
Идиоматичный функциональный код
Идиоматичный функциональный кодИдиоматичный функциональный код
Идиоматичный функциональный код
Alexander Granin
 
Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++
Alexander Granin
 

More from Alexander Granin (20)

Concurrent applications with free monads and stm
Concurrent applications with free monads and stmConcurrent applications with free monads and stm
Concurrent applications with free monads and stm
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fp
 
Final tagless vs free monad
Final tagless vs free monadFinal tagless vs free monad
Final tagless vs free monad
 
О разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop developmentО разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop development
 
Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...
 
Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...
 
Закон Деметры / Demetra's law
Закон Деметры / Demetra's lawЗакон Деметры / Demetra's law
Закон Деметры / Demetra's law
 
Design of big applications in FP
Design of big applications in FPDesign of big applications in FP
Design of big applications in FP
 
GitHub - зеркало разработчика
GitHub - зеркало разработчикаGitHub - зеркало разработчика
GitHub - зеркало разработчика
 
Functional programming in C++ LambdaNsk
Functional programming in C++ LambdaNskFunctional programming in C++ LambdaNsk
Functional programming in C++ LambdaNsk
 
Transition graph using free monads and existentials
Transition graph using free monads and existentialsTransition graph using free monads and existentials
Transition graph using free monads and existentials
 
Software transactional memory. pure functional approach
Software transactional memory. pure functional approachSoftware transactional memory. pure functional approach
Software transactional memory. pure functional approach
 
Вы не понимаете ФП / You don't understand FP
Вы не понимаете ФП / You don't understand FPВы не понимаете ФП / You don't understand FP
Вы не понимаете ФП / You don't understand FP
 
Functional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonadsFunctional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonads
 
Functional microscope - Lenses in C++
Functional microscope - Lenses in C++Functional microscope - Lenses in C++
Functional microscope - Lenses in C++
 
Дизайн больших приложений в ФП
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФП
 
Линзы - комбинаторная манипуляция данными
Линзы - комбинаторная манипуляция даннымиЛинзы - комбинаторная манипуляция данными
Линзы - комбинаторная манипуляция данными
 
Линзы - комбинаторная манипуляция данными (Dev2Dev)
Линзы - комбинаторная манипуляция данными (Dev2Dev)Линзы - комбинаторная манипуляция данными (Dev2Dev)
Линзы - комбинаторная манипуляция данными (Dev2Dev)
 
Идиоматичный функциональный код
Идиоматичный функциональный кодИдиоматичный функциональный код
Идиоматичный функциональный код
 
Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++
 

Recently uploaded

Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
ThomasParaiso2
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
DianaGray10
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
Rohit Gautam
 
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AIEnchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Vladimir Iglovikov, Ph.D.
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
Neo4j
 

Recently uploaded (20)

Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
 
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AIEnchancing adoption of Open Source Libraries. A case study on Albumentations.AI
Enchancing adoption of Open Source Libraries. A case study on Albumentations.AI
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
 

The Present and The Future of Functional Programming in C++

  • 1.
  • 2. The Present and The Future of Functional Programming in C++ Alexander Granin graninas@gmail.com C++ Siberia 2019
  • 3.
  • 4. Eric Niebler, C++ Siberia 2015 Ranges for the Standard Library
  • 5. Eric Niebler, C++ Siberia 2015 Ranges for the Standard Library Bartosz Milewski, С++ User Group 2014 Re-discovering monads in C++
  • 6. Eric Niebler, C++ Siberia 2015 Ranges for the Standard Library Bartosz Milewski, С++ User Group 2014 Re-discovering monads in C++ Ivan Čukić, C++ Siberia 2017 Atom heart monad (FRP in C++)
  • 7. My talks about Functional Programming in C++ С++ User Group 2014 Functional and Declarative Design in C++
  • 8. My talks about Functional Programming in C++ С++ User Group 2014 Functional and Declarative Design in C++ С++ Siberia 2015 Functional Microscope: Lenses in C++
  • 9. My talks about Functional Programming in C++ С++ User Group 2014 Functional and Declarative Design in C++ С++ Siberia 2015 Functional Microscope: Lenses in C++ С++ Russia 2016 Functional “Life”: Parallel Cellular Automata and Comonads in C++
  • 10. С++ User Group 2014 Functional and Declarative Design in C++ С++ Siberia 2015 Functional Microscope: Lenses in C++ С++ Russia 2016 Functional “Life”: Parallel Cellular Automata and Comonads in C++ С++ Russia 2018 Functional Approach to Software Transactional Memory in C++ My talks about Functional Programming in C++
  • 11. struct Presentation { Philosophy of Functional Programming in C++ Elements of Functional Programming in C++ Functional Design, Patterns and Approaches In C++ Limitations of Functional Programming in C++ };
  • 14. instructions, jumps, loops -- unstructured programming 14
  • 15. instructions, jumps, loops sequence, selection, iteration -- unstructured programming -- structured programming 15
  • 16. instructions, jumps, loops sequence, selection, iteration declaration, application, recursion -- unstructured programming -- functional programming -- structured programming 16
  • 17. class A {} template<> constexpr #define procedural programming metaprogramming functional programming object-oriented programming int main() 17
  • 19. C++ -> C++11/14 -> C++17/20Abstract C++ developer: C++ Developer Evolution
  • 20. C++ -> C++11/14 -> C++17/20 C++ -> Pain! -> C++11/14 -> My brain! -> C++17/20 Abstract C++ developer: Real C++ developer: C++ Developer Evolution
  • 21. C++ -> C++11/14 -> C++17/20 C++ -> Pain! -> C++11/14 -> My brain! -> C++17/20 C++ -> WTF -> Go Abstract C++ developer: Real C++ developer: Beginner C++ developer: C++ Developer Evolution
  • 22. C++ -> C++11/14 -> C++17/20 C++ -> Pain! -> C++11/14 -> My brain! -> C++17/20 C++ -> WTF -> Go C++ -> C++11/14 -> Why?!! -> Haskell -> C++17/20 Abstract C++ developer: Real C++ developer: Beginner C++ developer: Modern C++ developer: C++ Developer Evolution
  • 23. C++ -> C++11/14 -> C++17/20 C++ -> Pain! -> C++11/14 -> My brain! -> C++17/20 C++ -> WTF -> Go C++ -> C++11/14 -> Why?!! -> Haskell -> C++17/20 C++ -> C++11/14 -> Uh-Oh -> Rust Abstract C++ developer: Real C++ developer: Beginner C++ developer: Modern C++ developer: Tired C++ developer: C++ Developer Evolution
  • 24. C++ -> C++11/14 -> C++17/20 C++ -> Pain! -> C++11/14 -> My brain! -> C++17/20 C++ -> WTF -> Go C++ -> C++11/14 -> Why?!! -> Haskell -> C++17/20 C++ -> C++11/14 -> Uh-Oh -> Rust C++98 -> Please, leave me alone -> C++98 Abstract C++ developer: Real C++ developer: Beginner C++ developer: Modern C++ developer: Tired C++ developer: Old School C++ developer: C++ Developer Evolution
  • 26. Verbosity of imperative and OO code FP data types and constructs algebraic data types, higher order functions, lambdas, closures pattern-matching, currying, partial application Functional programming in my C++?!! 26
  • 27. Verbosity of imperative and OO code Unsafety, bugs and lack or guarantees FP data types and constructs Reliable FP concepts, guarantees purity, immutability, side effects control, type level programming recursion, range-based iteration, monoids, functors, monads... Functional programming in my C++?!! 27
  • 28. Verbosity of imperative and OO code Unsafety, bugs and lack or guarantees Leaking and heavy abstractions FP data types and constructs Reliable FP concepts, guarantees Declarative and functional design domain specific languages, persistent data types laziness, composition, combinators, first class functions Functional programming in my C++?!! 28
  • 29. Verbosity of imperative and OO code Unsafety, bugs and lack or guarantees Leaking and heavy abstractions Complexity of multithreaded programs FP data types and constructs Reliable FP concepts, guarantees Declarative and functional design Functional approaches functional reactive programming, software transactional memory, async / par / future monad, automatic parallelism Functional programming in my C++?!! 29
  • 31. 𝝺ambdas [](auto i) { return i + 1; } i -> i + 1 i => i + 1 lambda i: i + 1 | i | -> i + 1
  • 32. 𝝺ambdas in C++ <>(int x, int y) -> int {return x + y;} [|b|]() { return |b| -> set_text("World"); } i => i + 1 [](auto i) { return i + 1; } []<>(auto i) { return i + 1; }
  • 33. 𝝺ambdas in C++ Idea of the feature Standard issuing Feature adoption Feature improvements == You are standing here == Feature improvements <>(int x, int y) -> int {return x + y;} [|b|]() { return |b| -> set_text("World"); } i => i + 1 [](auto i) { return i + 1; } []<>(auto i) { return i + 1; }
  • 34. 𝝺ambdas in C++ Idea of the feature Standard issuing Feature adoption Feature improvements == You are standing here == Feature improvements 2011 ...2000... 2014, 2017 ...2011... 2020 2019 <>(int x, int y) -> int {return x + y;} [|b|]() { return |b| -> set_text("World"); } i => i + 1 [](auto i) { return i + 1; } []<>(auto i) { return i + 1; }
  • 35. Idea of the feature Pondering and thinking Reference implementation Discussions in Committee Drafting in Standard Implementation in compilers Standard issuing Feature adoption Feature improvements == You are standing here == Feature improvements 𝝺ambdas in C++ 2011 ...2000... <>(int x, int y) -> int {return x + y;} [|b|]() { return |b| -> set_text("World"); } i => i + 1 [](auto i) { return i + 1; } []<>(auto i) { return i + 1; } 2014, 2017 ...2011... 2008 - 2011 2006 - 2008 2020 2019
  • 36. What is 𝝺ambda? And who is 𝝺ambdaman? 36
  • 37. “ 𝝺ambda is just an object with operator() overloaded” std::vector<int> v {4, 2, 4}; struct Summator { int sum = 0; void operator()(int i) { sum += i; } }; Summator summator = std::for_each(v.begin(), v.end(), Summator()); std::cout << summator.sum; // 10 37
  • 38. “ 𝝺ambda is an anonymous function” std::vector<int> v {4, 2, 4}; auto sum = 0; std::for_each(v.begin(), v.end(), [&sum](int i) { sum += i; }); std::cout << sum; // 10 38
  • 39. “ 𝝺ambda is an universal combinator” auto I = [](auto x) { return x; }; auto K = [](auto x) { return [=](auto y) { return x; }; }; auto S = [](auto x) { return [=](auto y) { return [=](auto z) { return (x(z))(y(z)); }; }; }; Ix = x Kxy = x Sxyz = xz(yz) 39
  • 40. 𝝺ambdas evolution auto mul2 = [](int i) { return i * 2; } auto mul2 = [](auto i) { return i * 2; } constexpr auto mul2 = [](auto i) { return i * 2; } auto mul2 = []<typename T>(T i) { return i * 2; } auto mul2 = i => i * 2; C++11 C++14 C++17 C++20 C++?? Lambda expressions Polymorphic lambdas Constexpr lambdas “Familiar” syntax Abbreviated syntax 40
  • 48. Recursive constexpr pow() function using UInt = uint64_t; constexpr UInt pow(UInt a, UInt b) { return b == 0 ? 1 : a * pow(a, b - 1); } 48
  • 49. Recursive constexpr tower() function using UInt = uint64_t; constexpr UInt pow(UInt a, UInt b) { return b == 0 ? 1 : a * pow(a, b - 1); } constexpr UInt tower(UInt a, UInt b) { return b == 0 ? throw std::invalid_argument("b == 0") : b == 1 ? a : pow(a, tower(a, b - 1)); } 49
  • 50. Throwing exception at compile time? using UInt = uint64_t; constexpr UInt pow(UInt a, UInt b) { return b == 0 ? 1 : a * pow(a, b - 1); } constexpr UInt tower(UInt a, UInt b) { return b == 0 ? throw std::invalid_argument("b == 0") : b == 1 ? a : pow(a, tower(a, b - 1)); } 50
  • 52. constexpr UInt arr_impl(bool brackets_rec, UInt cnt, UInt a, UInt n, UInt b) { return brackets_rec ? (cnt == 0 ? ... ... ...) // recursion by brackets : (n == 1 ? pow(a, b) : n == 2 ? tower(a, b) : arr_impl(true, b - 1, a, n - 1, a)); // recursion by arrows } Double recursion constexpr arr_impl() function 52
  • 53. constexpr UInt arr(UInt a, UInt n, UInt b) { return arr_impl(false, 0, a, n, b); } constexpr UInt x1 = arr(3, 2, 3); // Compile-time evaluated UInt x2 = arr(3, 2, 3); // Has to be compile-time evaluated // 3 ↑↑ 3 = 7625597484987 Evaluation 53
  • 54. Pure Template Functional Programming in C++ 54
  • 55. Template Pow “function” template <UInt A, UInt N> struct Pow { static constexpr UInt value = A * Pow<A, N - 1>::value; }; template <UInt A> struct Pow<A, 0> { static constexpr UInt value = 1; }; 55
  • 56. Template Pow “function” template <UInt A, UInt N> struct Pow { static constexpr UInt value = A * Pow<A, N - 1>::value; }; template <UInt A> struct Pow<A, 0> { static constexpr UInt value = 1; }; 56 “Pat n c i g” “Rec on”
  • 57. Template Tower “function” template <UInt A, UInt B> struct Tower { static constexpr UInt value = Pow<A, Tower<A, B - 1>::value>::value; }; template <UInt A> struct Tower<A, 1> { static constexpr UInt value = A; }; 57
  • 58. Template ArrImpl “function” template <bool brackets_rec, UInt C, UInt A, UInt S, UInt B> struct ArrImpl { static constexpr UInt value = 1; }; template <UInt C, UInt A, UInt S, UInt B> struct ArrImpl<true, C, A, S, B> { static constexpr UInt value = ArrImpl<false, 0, A, ArrImpl<true, C - 1, A, S, B>::value, S>::value; }; ... // More template code 58
  • 59. “Evaluation” template <UInt A, UInt S, UInt B> struct Arr { static constexpr UInt value = ArrImpl<false, 0, A, S, B>::value; }; auto result = Arr<3, 2, 3>::value; // 3 ↑↑ 3 = 7625597484987 59
  • 60. Template ⇨ constexpr = 👍 template <UInt A, UInt S, UInt B> struct Arr { static constexpr UInt value = arr_impl(false, 0, A, S, B); }; 60
  • 61. Constexpr ⇨ template = ☠ template <UInt A, UInt S, UInt B> struct Arr { static constexpr UInt value = arr_impl(false, 0, A, S, B); }; // Won’t compile: constexpr UInt arr(UInt a, UInt s, UInt b) { return ArrImpl<false, 0, a, s, b>::value; } 61
  • 62. Constexpr ⇨ template = ☠ template <UInt A, UInt S, UInt B> struct Arr { static constexpr UInt value = arr_impl(false, 0, A, S, B); }; // Won’t compile: constexpr UInt arr(UInt a, UInt s, UInt b) { return ArrImpl<false, 0, a, s, b>::value; } 62 Dep n y e ??
  • 63. template <UInt A, UInt S, UInt B> struct Arr { static constexpr UInt value = arr_impl(false, 0, A, S, B); }; template <UInt A, UInt S, UInt B> constexpr UInt arr() { return ArrImpl<false, 0, A, S, B>::value; } Template constexpr! 63
  • 66. expected<T, E>: Proposal P0323R2 expected<double, error_condition> safe_divide(double i, double j) { if (j == 0) { return make_unexpected(arithmetic_error::divide_by_zero); } else { return i / j; } } 66
  • 67. template <typename T, typename E> using Expected = std::variant<T, E>; enum class Errors { ZeroTowerError = 0, ZeroDivisionError = 1 }; using UInt = uint64_t; using SafeInt = Expected<UInt, Errors>; constexpr SafeInt make_pure (const UInt& v) { return { v }; } constexpr SafeInt make_error(const Errors& e) { return { e }; } Custom Expected<T, E> 67 Sum p i g d::va t
  • 68. template <typename T, typename E> using Expected = std::variant<T, E>; enum class Errors { ZeroTowerError = 0, ZeroDivisionError = 1 }; using UInt = uint64_t; using SafeInt = Expected<UInt, Errors>; constexpr SafeInt make_pure (const UInt& v) { return { v }; } constexpr SafeInt make_error(const Errors& e) { return { e }; } Custom Expected<T, E> 68 Sup t e r & al
  • 69. template <typename T, typename E> using Expected = std::variant<T, E>; enum class Errors { ZeroTowerError = 0, ZeroDivisionError = 1 }; using UInt = uint64_t; using SafeInt = Expected<UInt, Errors>; constexpr SafeInt make_pure (const UInt& v) { return { v }; } constexpr SafeInt make_error(const Errors& e) { return { e }; } Custom Expected<T, E> 69 Con r r
  • 70. std::variant<UInt, Errors> val = make_pure(10); UInt result = std::holds_alternative<UInt>(val) ? std::get<UInt>(val) : throw std::runtime_error("Error got."); Extracting values of variant<> 70
  • 71. Pattern Matching? struct SafeIntVisitor { void operator()(const UInt& i) { cout << "Result: " << i; } void operator()(const Errors& e) { cout << "Error: " << e; } }; std::visit(SafeIntVisitor(), val); inspect (val) { <UInt> i: cout << "Result: " << i; <Errors> e: cout << "Error: " << e; }; 71 Vis g d::va t
  • 72. Pattern Matching! struct SafeIntVisitor { void operator()(const UInt& i) { cout << "Result: " << i; } void operator()(const Errors& e) { cout << "Error: " << e; } }; std::visit(SafeIntVisitor(), val); inspect (val) { <UInt> i: cout << "Result: " << i; <Errors> e: cout << "Error: " << e; }; 72 Pat n c i g Pro l P1260R0
  • 73. Object-oriented programming is an exceptionally bad idea which could only have originated in California. -- Edsger Dijkstra 73
  • 74. Functional Design, Patterns and Approaches in C++
  • 75. Monadic error handling with Expected<T, E> template <typename T, typename E> using Expected = std::variant<T, E>; enum class Errors { ZeroTowerError = 0, ZeroDivisionError = 1 }; using UInt = uint64_t; using SafeInt = Expected<UInt, Errors>; constexpr SafeInt make_pure (const UInt& v) { return { v }; } constexpr SafeInt make_error(const Errors& e) { return { e }; } 75
  • 76. UInt pow(UInt a, UInt n) { ... } UInt tower(UInt a, UInt b) { return b == 0 ? throw std::invalid_argument("b == 0") : b == 1 ? a : pow(a, tower(a, b - 1)); } Unsafe tower() function 76
  • 77. UInt pow(UInt a, UInt n) { ... } SafeInt safe_tower(UInt a, UInt b) { return b == 0 ? make_error(Errors::ZeroTowerError) : b == 1 ? a : pow(a, tower(a, b - 1)); } safe_tower() function 77
  • 78. UInt pow(UInt a, UInt n) { ... } SafeInt safe_tower(UInt a, UInt b) { return b == 0 ? make_error(Errors::ZeroTowerError) : b == 1 ? a : pow(a, tower(a, b - 1)); } safe_tower() function 78
  • 79. UInt pow(UInt a, UInt n) { ... } SafeInt safe_tower(UInt a, UInt b) { return b == 0 ? make_error(Errors::ZeroTowerError) : b == 1 ? a : pow(a, tower(a, b - 1)); } safe_tower() function 79
  • 80. UInt pow(UInt a, UInt n) { ... } SafeInt safe_tower(UInt a, UInt b) { return b == 0 ? make_error(Errors::ZeroTowerError) : b == 1 ? make_pure(a) : make_pure(pow(a, tower(a, b - 1))); } safe_tower() function 80
  • 81. UInt pow(UInt a, UInt n) { ... } SafeInt safe_tower(UInt a, UInt b) { return b == 0 ? make_error(Errors::ZeroTowerError) : b == 1 ? make_pure(a) : make_pure(pow(a, tower(a, b - 1))); } safe_tower() function 81
  • 82. UInt pow(UInt a, UInt n) { ... } SafeInt safe_tower(UInt a, UInt b) { return b == 0 ? make_error(Errors::ZeroTowerError) : b == 1 ? make_pure(a) : make_pure(pow(a, tower(a, b - 1))); } safe_tower() function 82
  • 83. UInt pow(UInt a, UInt n) { ... } SafeInt safe_tower(UInt a, UInt b) { return b == 0 ? make_error(Errors::ZeroTowerError) : b == 1 ? make_pure(a) : make_pure(pow(a, safe_tower(a, b - 1))); } safe_tower() function 83
  • 84. UInt pow(UInt a, UInt n) { ... } SafeInt safe_tower(UInt a, UInt b) { return b == 0 ? make_error(Errors::ZeroTowerError) : b == 1 ? make_pure(a) : make_pure(pow(a, safe_tower(a, b - 1))); } safe_tower() function 84
  • 85. UInt pow(UInt a, UInt n) { ... } SafeInt safe_tower(UInt a, UInt b) { return b == 0 ? make_error(Errors::ZeroTowerError) : b == 1 ? make_pure(a) : make_pure(pow(a, safe_tower(a, b - 1))); } safe_tower() function 85
  • 86. UInt pow(UInt a, UInt n) { ... } SafeInt safe_tower(UInt a, UInt b) { return b == 0 ? make_error(Errors::ZeroTowerError) : b == 1 ? make_pure(a) : mbind(safe_tower(a, b - 1), [=](UInt v) { return make_pure(pow(a, v)); } ); } Monadic binding* 86 * Almost
  • 87. UInt pow(UInt a, UInt n) { ... } SafeInt safe_tower(UInt a, UInt b) { return b == 0 ? make_error(Errors::ZeroTowerError) : b == 1 ? make_pure(a) : mbind(safe_tower(a, b - 1), [=](UInt v) { return make_pure(pow(a, v)); } ); } Monadic binding* 87 * Almost SafeInt mbind (SafeInt, Func<SafeInt, UInt>) mbind :: SafeInt -> (UInt -> SafeInt) -> SafeInt
  • 88. template <typename T, typename E, typename Lambda> SafeInt mbind(SafeInt safe_val, Lambda lambda) { return std::holds_alternative<E>(safe_val) ? safe_val : lambda(std::get<T>(safe_val)); } mbind() function 88
  • 89. auto mul10 = [](UInt i) { return make_pure(i * 10); }; SafeInt v1 = safe_tower(2, 0); SafeInt v2 = mbind(v1, mul10); std::visit(SafeIntVisitor(), v1); // error : 0 std::visit(SafeIntVisitor(), v2); // error : 0 Monadic chaining*, error path 89 * Almost
  • 90. auto mul10 = [](UInt i) { return make_pure(i * 10); }; SafeInt v1 = safe_tower(2, 3); SafeInt v2 = mbind( mbind(v1, mul10), mul10 ); std::visit(SafeIntVisitor(), v1); // result: 16 std::visit(SafeIntVisitor(), v2); // result: 1600 Monadic chaining*, success path 90 * Almost
  • 91. auto mul10 = [](UInt i) { return make_pure(i * 10); }; SafeInt v1 = safe_tower(2, 3); SafeInt v2 = mbind( mbind(v1, mul10), mul10 ); SafeInt v2 = do { UInt i1 <- safe_tower(2, 3); UInt i2 <- mul10(i1); return mul10(i2); } Monadic chaining*, do-notation dream 91 * Almost m i d d e n “<-”
  • 92. expected<int, Errors> safe_calculate(int a, int b) { do { UInt v <- safe_tower(a, b); int r <- safe_divide(v, b); return r; } } Do-notation dreams expected<int, Errors> safe_calculate(int a, int b) { UInt v = try safe_tower(a, b); int r = try safe_divide(v, b); return r; } 92 Has l-li “do” Pro l P0650R1 “C++ Mon In e f ”
  • 93. MONADS It’s what we like memes to be about 93
  • 94. expected<int, Errors> safe_calculate(int a, int b) { do { UInt v <- safe_tower(a, b); int r <- safe_divide(v, b); return r; } } Monads everywhere: expected<> 94 mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E>
  • 95. optional<int> same_age_persons_count(int personId) { do { Person p <- get(personId); Persons ps <- find( [=](Person x){ return x.age == p.age; } ); return ps.size(); } } Monads everywhere: optional<> 95 mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E> mbind :: optional<A> -> (A -> optional<B>) -> optional<B>
  • 96. future<int> calculate(int a, int b) { do { int x <- heavy_calc(a); int y <- heavy_calc(b); return heavy_calc(x + y); } } Monads everywhere: future<> 96 mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E> mbind :: optional<A> -> (A -> optional<B>) -> optional<B> mbind :: future<A> -> (A -> future<B>) -> future<B>
  • 97. async<Result> request_person(int personId) { do { auto person <- request_person(personId); auto confs <- request_conferences(personId); bool saved1 <- save(person); bool saved2 <- save(confs); return {saved1 && saved2, person, confs}; } } Monads everywhere: async<> (coroutines?) 97 mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E> mbind :: optional<A> -> (A -> optional<B>) -> optional<B> mbind :: future<A> -> (A -> future<B>) -> future<B> mbind :: async<A> -> (A -> async<B>) -> async<B>
  • 98. parser<Person> person() { do { _ <- many(space); first_name <- name(); _ <- many(space); last_name <- name(); return {first_name, last_name}; } } Monads everywhere: parser<> 98 mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E> mbind :: optional<A> -> (A -> optional<B>) -> optional<B> mbind :: future<A> -> (A -> future<B>) -> future<B> mbind :: async<A> -> (A -> async<B>) -> async<B> mbind :: parser<A> -> (A -> parser<B>) -> parser<B>
  • 101. 101
  • 103. 103 auto triples = for_each(iota(1), [](int z) { return for_each(iota(1, z+1), [=](int x) { return for_each(iota(x, z+1), [=](int y) { return yield_if(x*x + y*y == z*z, make_tuple(x, y, z)); }); }); }); Pythagorean Triples in Ranges
  • 104. 104 auto triples = for_each(iota(1), [](int z) { return for_each(iota(1, z+1), [=](int x) { return for_each(iota(x, z+1), [=](int y) { return yield_if(x*x + y*y == z*z, make_tuple(x, y, z)); }); }); }); Pythagorean Triples in Ranges
  • 105. 105 auto triples = for_each(iota(1), [](int z) { return for_each(iota(1, z+1), [=](int x) { return for_each(iota(x, z+1), [=](int y) { return yield_if(x*x + y*y == z*z, make_tuple(x, y, z)); }); }); }); for(auto triple : triples | view::take(10)) { cout << '(' << get<0>(triple) << ',' << get<1>(triple) << ',' << get<2>(triple) << ')' << 'n'; } Pythagorean Triples in Ranges Output: (3,4,5) (6,8,10) (5,12,13) (9,12,15) (8,15,17) (12,16,20) (7,24,25) (15,20,25) (10,24,26) (20,21,29)
  • 106. 106 Pythagorean Triples in Ranges, reformatted auto triples = for_each(iota(1), [] (int z) { return for_each(iota(1, z+1), [=](int x) { return for_each(iota(x, z+1), [=](int y) { return yield_if(x*x + y*y == z*z, make_tuple(x, y, z)); }); }); });
  • 107. 107 Looks familiar... auto triples = for_each(iota(1), [] (int z) { return for_each(iota(1, z+1), [=](int x) { return for_each(iota(x, z+1), [=](int y) { return yield_if(x*x + y*y == z*z, make_tuple(x, y, z)); }); }); }); iota :: list<int> for_each :: list<int> -> (int -> list<int>) -> list<int>
  • 108. 108 for_each → mbind... auto triples = mbind(iota(1), [] (int z) { return mbind(iota(1, z+1), [=](int x) { return mbind(iota(x, z+1), [=](int y) { return yield_if(x*x + y*y == z*z, make_tuple(x, y, z)); }); }); }); iota :: list<int> for_each :: list<int> -> (int -> list<int>) -> list<int> mbind :: list<int> -> (int -> list<int>) -> list<int>
  • 109. 109 Monads, again?? auto triples = mbind(iota(1), [] (int z) { return mbind(iota(1, z+1), [=](int x) { return mbind(iota(x, z+1), [=](int y) { return yield_if(x*x + y*y == z*z, make_tuple(x, y, z)); }); }); }); auto triples = do { int z <- iota(1); int x <- iota(1, z+1); int y <- iota(x, z+1); guard (x*x + y*y == z*z); return make_tuple(x, y, z); }
  • 110. 110 auto triples = mbind(iota(1), [] (int z) { return mbind(iota(1, z+1), [=](int x) { return mbind(iota(x, z+1), [=](int y) { return yield_if(x*x + y*y == z*z, make_tuple(x, y, z)); }); }); }); auto triples = do { int z <- iota(1); int x <- iota(1, z+1); int y <- iota(x, z+1); guard (x*x + y*y == z*z); return make_tuple(x, y, z); } Monadic Pythagorean Triples in Haskell triples = do z <- [1..] x <- [1..z] y <- [x..z] guard (x*x + y*y == z*z) pure (x, y, z)
  • 111. 111 It’s inevitable. This is terrifying. mbind :: expected<A, E> -> (A -> expected<B, E>) -> expected<B, E> // error handling mbind :: optional<A> -> (A -> optional<B>) -> optional<B> // absent values mbind :: future<A> -> (A -> future<B>) -> future<B> // parallelism mbind :: async<A> -> (A -> async<B>) -> async<B> // callback hell elimination mbind :: parser<A> -> (A -> parser<B>) -> parser<B> // parsing mbind :: list<A> -> (A -> list<B>) -> list<B> // combinatorics (kind of) mbind :: reader<A> -> (A -> reader<B>) -> reader<B> // environment data mbind :: writer<A> -> (A -> writer<B>) -> writer<B> // write-only data mbind :: state<A> -> (A -> state<B>) -> state<B> // monadic state mbind :: io<A> -> (A -> io<B>) -> io<B> // effects control
  • 112. 112 for(auto triple : triples | view::take(10)) { cout << '(' << get<0>(triple) << ',' << get<1>(triple) << ',' << get<2>(triple) << ')' << 'n'; } Functional composition with ranges Output: (3,4,5) (6,8,10) (5,12,13) (9,12,15) (8,15,17) (12,16,20) (7,24,25) (15,20,25) (10,24,26) (20,21,29)
  • 113. 113 for(auto triple : triples | view::take(10) | view::transform(mul10_middle)) { cout << '(' << get<0>(triple) << ',' << get<1>(triple) << ',' << get<2>(triple) << ')' << 'n'; } auto mul10_middle = [](const tuple<int, int, int>& t) { const auto& [x, y, z] = t; return make_tuple(x, y * 10, z); }; Functional composition with ranges Output: (3,40,5) (6,80,10) (5,120,13) (9,120,15) (8,150,17) (12,160,20) (7,240,25) (15,200,25) (10,240,26) (20,210,29)
  • 114. 114 for(auto triple : triples | view::take(10) | view::transform(mul10_middle) | view::reverse) { cout << '(' << get<0>(triple) << ',' << get<1>(triple) << ',' << get<2>(triple) << ')' << 'n'; } auto mul10_middle = [](const tuple<int, int, int>& t) { const auto& [x, y, z] = t; return make_tuple(x, y * 10, z); }; Functional composition with ranges Output: (20,210,29) (10,240,26) (15,200,25) (7,240,25) (12,160,20) (8,150,17) (9,120,15) (5,120,13) (6,80,10) (3,40,5)
  • 116. 116 “Problems” of Functional Programming in C++ ● Compilation time ● Hard debugging ● Performance
  • 117. 117 Issues of Functional Programming in C++ ● Absence of currying ● Dangerous closures ● Lambdas are verbose ● Tuple is extremely verbose
  • 118. 118 Real Problems of Functional Programming in C++ ● Poor type system ○ No real Algebraic Data Types ○ No real function type ○ Lambdas have unique types ○ No real pattern matching (yet) ■ Won’t be expression?? ○ Type inference is weak ● Composition of functions is complicated ● No native support of monads (in 2019)
  • 119. 119 Real Problems of Functional Programming in C++ C++ ● Poor type system ○ No real Algebraic Data Types ○ No real function type ○ Lambdas have unique types ○ No real pattern matching (yet) ■ Won’t be expression?? ○ Type inference is weak ● Composition of functions is complicated ● No native support of monads (in 2019)
  • 120. Prediction for high-level C++ time High-level C++ adoption 2020 New high-level features 2023 120
  • 121. 121 GitHub List: Functional Programming in C++ https://github.com/graninas/cpp_functional_programming👉 ● Books ● Articles ● Papers ● Talks ● QA ● Libraries ● Showcase projects
  • 122. 122
  • 123. Thanks for watching! Let’s talk? C++ Siberia 2019 Alexander Granin graninas@gmail.com
  • 124. ???
  • 125. 125