2. Who I am?
● C++, Haskell, C#
● C++ User Group Novosibirsk, 2014
“Functional Declarative Design in C++”
● C++ Siberia Novosibirsk, 2015
“Functional Microscope: Lenses in C++”
● Talks, articles, research on FP in general, FP in C++
5. C++ FP Enthusiasts
● Range v3 by Eric Niebler - proposal for C++ Standard Lib
● FTL (Functional Template Library) by Bjorn Aili
● Cat by Nicola Bonelli - Category Theory elements
● Bartosz Milewski
● John Carmack
● …
● <Place your name here>
6. С++ User Group Novosibirsk, 2014
“Functional Declarative Design in C++”
8. FP elements in C++
● Lambdas, closures, functions (almost pure)
● std::function<>
● Immutability, POD-types
● Templates - pure functional language
● for_each(), recursion
● C++ Concepts: coming soon...
9. 9
Simple 1-dimensional 3-state CA
● 1 dimension
● 3 states: A (“Alive”), P (“Pregnant”), D/space (“Dead”),
A A
A A
A A
P
P
A A A
1 gen P
2 gen A A A
3 gen A A A A
4 gen A P A
5 gen A A A
6 gen A A A A
7 gen A P A
10. template <typename T>
struct Universe {
std::vector<T> field;
int position;
};
typedef char Cell;
const Cell Pregnant = 2;
const Cell Alive = 1;
const Cell Dead = 0;
Universe<Cell>
A A A A
Universe<T>: Pointed array
Universe<Cell> u;
u.field = {D, A, A, D, A, A, D};
u.position = 3;
11. Immutable shift
A A A A
Universe<Cell> left (const Universe<Cell>& u) {
Universe<Cell> newU
{ u.field, u.position - 1 };
if (u.position == 0)
newU.position = u.size() - 1;
return newU;
}
Universe<Cell> right (const Universe<Cell>& u);
A A A A
A A A A
shift to right
shift to left
12. Observing: shift and extract
A A A A
Cell extract(const Universe<Cell>& u) {
return u.field[u.position];
}
Universe<Cell> u = {...};
Cell cur = extract (u);
Cell r = extract (right (u));
Cell rr = extract (right (right (u)));
Cell l = extract (left (u));
Cell ll = extract (left (left (u)));
D
A A A A
shift to left
shift to left
extract
13. Rule: observe and reduce
A A A A
P
Cell rule(const Universe<Cell>& row) {
// extract l, ll, cur, r, rr here
if (isA(l) && isA(r) && !isAorP(cur))
return Pregnant;
// ... more rules here
return Dead;
}
14. Applying rule: extend, extract
Cell rule (Universe<Cell> row)
Universe<Cell> extend (
std::function<Cell(Universe<Cell>)> f,
Universe<Cell> u)
A A A A
P
P
15. Step: duplicate, (for_each: extend, extract)
A A A A
A A A A
A A A A
A A A A
A A A A
A A A A
A A A A A
P
A
A
P
A
Cell rule (Universe<Cell> row)
Universe<Cell> extend (
std::function<Cell(Universe<Cell>)> f,
Universe<Cell> u)
Universe<Universe<Cell>>
duplicate (Universe<Cell> u)
Universe<Cell> left (Universe<Cell> u)
Universe<Cell> right (Universe<Cell> u)
16. 16
Generic functional approach
#define UT Universe<T>
#define UUT Universe<Universe<T>>
template <typename T> T rule (const UT& u)
template <typename T> UT left (const UT& u)
template <typename T> UT right (const UT& u)
30. fmap2
template <typename T> UUT fmap2 (
const func<T(UUT)>& f,
const UUUUT& uuut)
{
const func<UT(UUUT)> f2 = [=](const UUUT& uuut2)
{
// Something really complicated here with using of ‘f’.
};
return { map (f2, uuut.field), uuut.position }; // parallelization: map -> mapPar
}
31. Game of Life benchmark
Field side Sequential Parallel
(microseconds)
50 484 283
100 3900 2291
150 12669 8005
200 30278 19415
32. Game of Life on comonads, C++
● Highly experimental
● Sequential, async and parallel GoL
● Simple 1D 3-state CA
● Functional design
● https://github.com/graninas/CMLife
● Клеточные автоматы и комонады, by Hithroc Mehatoko