Monadic parsers in C++

Alexander Granin
Alexander GraninSoftware Developer, Independent Consultant at Independent Consultant
Monadic parsers
Alexander Granin
graninas@gmail.com
C++ Russia 2019, Moscow
1
Monadic parsers in C++
С++ Siberia 2019, Keynote
The Present and the Future of Functional Programming in C++
С++ Russia 2018
Functional Approach to Software Transactional Memory in C++
С++ Russia 2016
Functional “Life”: Parallel Cellular Automata and Comonads in C++
С++ Siberia 2015
Functional Microscope: Lenses in C++
С++ User Group 2014
Functional and Declarative Design in C++
3
struct Presentation
{
Introduction
Parsing and Backus-Naur form
boost::spirit (qi)
cpp_parsec_free
Monadic parsers
State & context-sensitive grammars
Conclusion
};
4
age
integer
first name
string
last name
string
salary
float
employee {35, “Jane”, “Street”, 54321}
struct Employee
{
int age;
string firstName;
string lastName;
double salary;
};
Parsing
5
employee ::=
"employee" spaces
"{" spaces
age "," spaces
firstName "," spaces
lastName "," spaces
salary spaces
"}"
Backus-Naur Form
quotedString ::= '"' string '"'
age ::= integer
firstName ::= quotedString
lastName ::= quotedString
salary ::= double
6
boost::spirit (Qi)
7
quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
start %= lit("employee") >> '{'
>> int_ >> ','
>> quoted_string >> ','
>> quoted_string >> ','
>> double_ >> '}';
}
8
quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
start %= lit("employee") >> '{'
>> int_ >> ','
>> quoted_string >> ','
>> quoted_string >> ','
>> double_ >> '}';
}
qi::rule<Iterator, string(), ascii::space_type> quoted_string;
qi::rule<Iterator, employee(), ascii::space_type> start;
9
template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>{
employee_parser() : employee_parser::base_type(start) {
quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
start %= lit("employee") >> '{'
>> int_ >> ','
>> quoted_string >> ','
>> quoted_string >> ','
>> double_ >> '}';
}
qi::rule<Iterator, string(), ascii::space_type> quoted_string;
qi::rule<Iterator, employee(), ascii::space_type> start;
};
10
template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>{
employee_parser() : employee_parser::base_type(start) {
quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
start %= lit("employee") >> '{'
>> int_ >> ','
>> quoted_string >> ','
>> quoted_string >> ','
>> double_ >> '}';
}
qi::rule<Iterator, string(), ascii::space_type> quoted_string;
qi::rule<Iterator, employee(), ascii::space_type> start;
};
11
12
cpp_parsec_free
13
ParserT<Employee> employee =
app<Employee, int, string, string, double>(
mkEmployee,
prefix >> intP,
comma >> quotedString,
comma >> quotedString,
comma >> (doubleP << postfix));
14
ParserT<Employee> employee =
app<Employee, int, string, string, double>(
mkEmployee,
prefix >> intP,
comma >> quotedString,
comma >> quotedString,
comma >> (doubleP << postfix));
auto prefix = lit("employee") >> between(spaces, symbol('{'));
auto postfix = between(spaces, symbol('}'));
auto comma = symbol(',') >> spaces;
auto mkEmployee =
[](int a, const string& sn, const string& fn, double s) {
return Employee {a, sn, fn, s};
};
15
auto s = "employee {35, “Jane”, “Street”, 54321}";
ParserResult<Employee> result = parse(employee, s);
16
auto s = "employee {35, “Jane”, “Street”, 54321}";
ParserResult<Employee> result = parse(employee, s);
if (isLeft(result)) {
std::cout << "Parse error: " << getError(result).message;
}
else {
Employee employee = getParsed(result);
}
17
Parser combinators
18
ParserT<int> intP; // integer number
ParserT<double> doubleP; // double precision float
ParserT<Char> digit; // 0..9
ParserT<Char> lower; // a..z
ParserT<Char> upper; // A..Z
ParserT<Char> letter; // a..z A..Z
ParserT<Char> alphaNum; // 0..9 a..z A..Z
ParserT<Char> symbol(Char ch); // symbol
ParserT<string> lit(const string&); // string
Basic parsers
19
template <typename A, typename B>
ParserT<A> fst(const ParserT<A>& p1, const ParserT<B>& p2);
template <typename A, typename B>
ParserT<B> snd(const ParserT<A>& p1, const ParserT<B>& p2);
Parser combinators
20
template <typename A, typename B>
ParserT<A> fst(const ParserT<A>& p1, const ParserT<B>& p2);
template <typename A, typename B>
ParserT<B> snd(const ParserT<A>& p1, const ParserT<B>& p2);
// fst
template <typename A, typename B>
ParserT<A> operator<< (const ParserT<A>& l, const ParserT<B>& r);
// snd
template <typename A, typename B>
ParserT<B> operator>> (const ParserT<A>& l, const ParserT<B>& r);
Parser combinators
21
ParserT<string> helloWorld =
snd(lit("Hello"), snd(symbol(' '), lit("world")));
ParserT<string> helloWorld =
lit("Hello") >> symbol(' ') >> lit("world");
Parsing “Hello world”
22
template <typename A>
ParserT<Many<A>> many(const ParserT<A>& p); // 0 or many
template <typename A>
ParserT<Many<A>> many1(const ParserT<A>& p); // 1 or many
template <typename A, typename B>
ParserT<B> between(const ParserT<A>& bracketP, // between
const ParserT<B>& p);
More combinators
23
template <typename A>
ParserT<A> alt(const ParserT<A>& l, const ParserT<A>& r);
template <typename A>
ParserT<A> operator| (const ParserT<A>& l, const ParserT<A>& r);
Alternative
24
template <typename A>
ParserT<A> alt(const ParserT<A>& l, const ParserT<A>& r);
template <typename A>
ParserT<A> operator| (const ParserT<A>& l, const ParserT<A>& r);
ParserT<string> boolean = alt(lit("true"), lit("false"));
ParserT<string> currency = lit("EUR") | lit("USD") | lit("GBP");
Alternative
25
Monadic parsers
26
Functor
fmap :: (A -> B) -> ParserT<A> -> ParserT<B>
Applicative
app :: (A -> B -> C) -> ParserT<A> -> ParserT<B> -> ParserT<C>
Monad
bind :: ParserT<A> -> (A -> ParserT<B>)
27
fmap :: (A -> B) -> ParserT<A> -> ParserT<B>
template <typename A, typename B>
ParserT<B> fmap(const function<B(A)>& f, const ParserT<A>& p);
Functor
28
fmap :: (A -> B) -> ParserT<A> -> ParserT<B>
template <typename A, typename B>
ParserT<B> fmap(const function<B(A)>& f, const ParserT<A>& p);
ParserT<string> strBoolean = lit("true") | lit("false");
Functor
29
fmap :: (A -> B) -> ParserT<A> -> ParserT<B>
template <typename A, typename B>
ParserT<B> fmap(const function<B(A)>& f, const ParserT<A>& p);
ParserT<string> strBoolean = lit("true") | lit("false");
ParserT<bool> boolean = fmap<string, bool>(f, strBoolean);
function<bool(string)> f = [](const string& s) {
return s == "true";
};
Functor
30
Functor
fmap :: (A -> B) -> ParserT<A> -> ParserT<B>
Applicative
app :: (A -> B -> C) -> ParserT<A> -> ParserT<B> -> ParserT<C>
Monad
bind :: ParserT<A> -> (A -> ParserT<B>)
31
app :: (A -> B -> C) -> ParserT<A> -> ParserT<B> -> ParserT<C>
template <typename A, typename B, typename C>
ParserT<C> app(const function<C(A, B)>& f,
const ParserT<A>& a, const ParserT<B>& b);
Applicative
32
app :: (A -> B -> C) -> ParserT<A> -> ParserT<B> -> ParserT<C>
template <typename A, typename B, typename C>
ParserT<C> app(const function<C(A, B)>& f,
const ParserT<A>& a, const ParserT<B>& b);
ParserT<string> helloUsername = app<string, string>(
mkHello,
letters,
spaces >> letters);
string mkHello = [](const string& firstName, const string& secondName) {
return string("Hello, ") + firstName + " " + secondName + "!"; };
Applicative
33
ParserT<Value> value = app(mkValue, intP | doubleP);
Applicative is combinable
34
ParserT<Value> value = app(mkValue, intP | doubleP);
ParserT<BinOp> binOp = app(mkBinOp,
symbol('+') | symbol('-') | symbol('*') | symbol('/'));
Applicative is combinable
35
ParserT<Value> value = app(mkValue, intP | doubleP);
ParserT<BinOp> binOp = app(mkBinOp,
symbol('+') | symbol('-') | symbol('*') | symbol('/'));
ParserT<FuncArgs> funcArgs = app(mkFuncArgs,
expr, opt(symbol(',') >> funcArgs));
Applicative is combinable
36
ParserT<Value> value = app(mkValue, intP | doubleP);
ParserT<BinOp> binOp = app(mkBinOp,
symbol('+') | symbol('-') | symbol('*') | symbol('/'));
ParserT<FuncArgs> funcArgs = app(mkFuncArgs,
expr, opt(symbol(',') >> funcArgs));
ParserT<FuncCall> funcCall = app(mkFuncCall,
identifier, between('(', ')', funcArgs));
Applicative is combinable
37
ParserT<Value> value = app(mkValue, intP | doubleP);
ParserT<BinOp> binOp = app(mkBinOp,
symbol('+') | symbol('-') | symbol('*') | symbol('/'));
ParserT<FuncArgs> funcArgs = app(mkFuncArgs,
expr, opt(symbol(',') >> funcArgs));
ParserT<FuncCall> funcCall = app(mkFuncCall,
identifier, between('(', ')', funcArgs));
ParserT<BinExpr> binExpr = app(mkBinExpr, expr, binOp, expr);
Applicative is combinable
38
ParserT<Value> value = app(mkValue, intP | doubleP);
ParserT<BinOp> binOp = app(mkBinOp,
symbol('+') | symbol('-') | symbol('*') | symbol('/'));
ParserT<FuncArgs> funcArgs = app(mkFuncArgs,
expr, opt(symbol(',') >> funcArgs));
ParserT<FuncCall> funcCall = app(mkFuncCall,
identifier, between('(', ')', funcArgs));
ParserT<BinExpr> binExpr = app(mkBinExpr, expr, binOp, expr);
ParserT<Expr> expr = app(mkExpr, binExpr | funcCall | value);
Applicative is combinable
39
Functor
fmap :: (A -> B) -> ParserT<A> -> ParserT<B>
Applicative
app :: (A -> B -> C) -> ParserT<A> -> ParserT<B> -> ParserT<B>
Monad
bind :: ParserT<A> -> (A -> ParserT<B>)
40
template <typename A>
ParserT<A> pure(const A& a);
template <typename A, typename B>
ParserT<B> bind(
const ParserT<A>& ma,
const function<ParserT<B>(A)>& f);
ParserT monad
41
ParserT<string> helloUsername =
bind<string, string>(letters, [=](auto firstName) {
return bind<string, string>(spaces, [=](auto) {
return bind<string, string>(letters, [=](auto lastName) {
return pure<string>(mkHello(firstName, lastName)); }); }); });
ParserT<string> helloUsername =
bind<string, string>(letters, [=](auto firstName) { return
bind<string, string>(spaces, [=](auto) { return
bind<string, string>(letters, [=](auto lastName) { return
pure<string>(mkHello(firstName, lastName)); }); }); });
Monadic binding
42
ParserT<string> helloUsername =
bind<string, string>(letters, [=](auto firstName) {
return bind<string, string>(spaces, [=](auto) {
return bind<string, string>(letters, [=](auto lastName) {
return pure<string>(mkHello(firstName, lastName)); }); }); });
ParserT<string> helloUsername =
bind<string, string>(letters, [=](auto firstName) { return
bind<string, string>(spaces, [=](auto) { return
bind<string, string>(letters, [=](auto lastName) { return
pure<string>(mkHello(firstName, lastName)); }); }); });
Monadic binding, reformatted
43
ParserT<string> helloUsername = do {
auto firstName <- letters;
auto _ <- spaces;
auto lastName <- letters;
return pure<string>(mkHello(firstName, lastName));
};
Dear Santa, I was a good boy last year. Can I have?..
44
State & context-sensitive grammars
45
age
integer
first name
string
last name
string
salary
float
employee {35, “Jane”, “Street”, 54321}
address {35, “Jane”, “Street”, 54321}
house
integer
title
string
post index
integer
type
string
46
struct Employee {
int age;
string firstName;
string lastName;
double salary;
};
47
struct Address {
int house;
string title;
string name;
int postIndex;
};
Algebraic Data Type
struct Employee {
int age;
string firstName;
string lastName;
double salary;
};
48
struct Address {
int house;
string title;
string name;
int postIndex;
};
using LogEntry = std::variant<Employee, Address>;
Algebraic Data Type
struct Employee {
int age;
string firstName;
string lastName;
double salary;
};
49
struct Address {
int house;
string title;
string name;
int postIndex;
};
using LogEntry = std::variant<Employee, Address>;
function<LogEntry(int a, const string& fn, const string& ln, double s)>
mkEmployeeEntry;
function<LogEntry(int h, const string& ttl, const string& n, int idx)>
mkAddressEntry;
Algebraic Data Type
struct Config {
string currentEntry;
};
ParserT<Config, string> logToken = lit("employee") | lit("address");
ParserT<Config, Unit> setEntry = bind<string, Unit>(
logToken,
[](const string& s) {
return putSt(Config { s });
});
Putting state
50
struct Config {
string currentEntry;
};
ParserT<Config, string> logToken = lit("employee") | lit("address");
ParserT<Config, Unit> setEntry = bind<string, Unit>(
logToken,
[](const string& s) {
return putSt(Config { s });
});
Putting state
51
ParserT<Config, LogEntry> logEntry =
bind<Config, LogEntry>(getSt, [=](Config cfg) {
if (cfg.currentEntry == "employee")
return fmap(mkEmployeeEntry, employeeParser);
return fmap(mkAddressEntry, addressParser);
});
Getting state
52
ParserT<Config, LogEntry> logEntry =
bind<Config, LogEntry>(getSt, [=](Config cfg) {
if (cfg.currentEntry == "employee")
return fmap(mkEmployeeEntry, employeeParser);
return fmap(mkAddressEntry, addressParser);
});
Getting state
53
Conclusion
54
Monadic parser combinators
● Monad: do-notation, bind, when, unless, sequence, mapM, guard
● Applicative: app, pure
● Alternative: alt, operator|
● Functor: fmap
● Time travelling: lookForward, lookBackward
● State handling: getSt, putSt
● Error handling: tryP, safeP, onFail, onSuccess, failWith
55
56
GitHub List: Functional Programming in C++
https://github.com/graninas/cpp_functional_programming��
● Books
● Articles
● Papers
● Talks
● QA
● Libraries
● Showcase projects
Thanks for watching!
Alexander Granin
graninas@gmail.com
Twitter: @graninas
C++ Russia 2019, Moscow
57
Monadic parsers in C++
1 of 58

Recommended

The present and the future of functional programming in c++ by
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
343 views125 slides
High performance web programming with C++14 by
High performance web programming with C++14High performance web programming with C++14
High performance web programming with C++14Matthieu Garrigues
3.5K views61 slides
2014 computer science_question_paper by
2014 computer science_question_paper2014 computer science_question_paper
2014 computer science_question_papervandna123
6.6K views15 slides
Lambda Expressions in C++ by
Lambda Expressions in C++Lambda Expressions in C++
Lambda Expressions in C++Patrick Viafore
614 views19 slides
Fun with Lambdas: C++14 Style (part 1) by
Fun with Lambdas: C++14 Style (part 1)Fun with Lambdas: C++14 Style (part 1)
Fun with Lambdas: C++14 Style (part 1)Sumant Tambe
6.7K views46 slides
Functions by
FunctionsFunctions
FunctionsKamal Acharya
848 views13 slides

More Related Content

What's hot

Practical Class 12th (c++programs+sql queries and output) by
Practical Class 12th (c++programs+sql queries and output) Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output) Aman Deep
74.8K views52 slides
Data structures lab manual by
Data structures lab manualData structures lab manual
Data structures lab manualSyed Mustafa
6.9K views48 slides
Data Structures Practical File by
Data Structures Practical File Data Structures Practical File
Data Structures Practical File Harjinder Singh
12.2K views76 slides
54602399 c-examples-51-to-108-programe-ee01083101 by
54602399 c-examples-51-to-108-programe-ee0108310154602399 c-examples-51-to-108-programe-ee01083101
54602399 c-examples-51-to-108-programe-ee01083101premrings
2.7K views54 slides
C++ Programming - 11th Study by
C++ Programming - 11th StudyC++ Programming - 11th Study
C++ Programming - 11th StudyChris Ohk
1.1K views18 slides
VTU Data Structures Lab Manual by
VTU Data Structures Lab ManualVTU Data Structures Lab Manual
VTU Data Structures Lab ManualNithin Kumar,VVCE, Mysuru
3.6K views32 slides

What's hot(20)

Practical Class 12th (c++programs+sql queries and output) by Aman Deep
Practical Class 12th (c++programs+sql queries and output) Practical Class 12th (c++programs+sql queries and output)
Practical Class 12th (c++programs+sql queries and output)
Aman Deep74.8K views
Data structures lab manual by Syed Mustafa
Data structures lab manualData structures lab manual
Data structures lab manual
Syed Mustafa6.9K views
Data Structures Practical File by Harjinder Singh
Data Structures Practical File Data Structures Practical File
Data Structures Practical File
Harjinder Singh12.2K views
54602399 c-examples-51-to-108-programe-ee01083101 by premrings
54602399 c-examples-51-to-108-programe-ee0108310154602399 c-examples-51-to-108-programe-ee01083101
54602399 c-examples-51-to-108-programe-ee01083101
premrings2.7K views
C++ Programming - 11th Study by Chris Ohk
C++ Programming - 11th StudyC++ Programming - 11th Study
C++ Programming - 11th Study
Chris Ohk1.1K views
Дмитрий Верескун «Синтаксический сахар C#» by SpbDotNet Community
Дмитрий Верескун «Синтаксический сахар C#»Дмитрий Верескун «Синтаксический сахар C#»
Дмитрий Верескун «Синтаксический сахар C#»
C++ Programming - 2nd Study by Chris Ohk
C++ Programming - 2nd StudyC++ Programming - 2nd Study
C++ Programming - 2nd Study
Chris Ohk2.2K views
project report in C++ programming and SQL by vikram mahendra
project report in C++ programming and SQLproject report in C++ programming and SQL
project report in C++ programming and SQL
vikram mahendra1.5K views
C++17 introduction - Meetup @EtixLabs by Stephane Gleizes
C++17 introduction - Meetup @EtixLabsC++17 introduction - Meetup @EtixLabs
C++17 introduction - Meetup @EtixLabs
Stephane Gleizes348 views
Object Oriented Programming Using C++ Practical File by Harjinder Singh
Object Oriented Programming Using C++ Practical FileObject Oriented Programming Using C++ Practical File
Object Oriented Programming Using C++ Practical File
Harjinder Singh14.9K views
Computer Science Practical Science C++ with SQL commands by Vishvjeet Yadav
Computer Science Practical Science C++ with SQL commandsComputer Science Practical Science C++ with SQL commands
Computer Science Practical Science C++ with SQL commands
Vishvjeet Yadav1.5K views
C++11 by ppd1961
C++11C++11
C++11
ppd19615.2K views
Technical questions for interview c programming by CHANDAN KUMAR
Technical questions for interview  c programmingTechnical questions for interview  c programming
Technical questions for interview c programming
CHANDAN KUMAR191 views

Similar to Monadic parsers in C++

Alexey Tsoy Meta Programming in C++ 16.11.17 by
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17LogeekNightUkraine
149 views20 slides
Rcpp: Seemless R and C++ by
Rcpp: Seemless R and C++Rcpp: Seemless R and C++
Rcpp: Seemless R and C++Romain Francois
3.3K views31 slides
NetPonto - The Future Of C# - NetConf Edition by
NetPonto - The Future Of C# - NetConf EditionNetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionPaulo Morgado
234 views39 slides
Tuga IT 2018 Summer Edition - The Future of C# by
Tuga IT 2018 Summer Edition - The Future of C#Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#Paulo Morgado
469 views38 slides
Unit 5 Foc by
Unit 5 FocUnit 5 Foc
Unit 5 FocJAYA
2.1K views238 slides
C++ manual Report Full by
C++ manual Report FullC++ manual Report Full
C++ manual Report FullThesis Scientist Private Limited
711 views36 slides

Similar to Monadic parsers in C++(20)

Alexey Tsoy Meta Programming in C++ 16.11.17 by LogeekNightUkraine
Alexey Tsoy Meta Programming in C++ 16.11.17Alexey Tsoy Meta Programming in C++ 16.11.17
Alexey Tsoy Meta Programming in C++ 16.11.17
LogeekNightUkraine149 views
NetPonto - The Future Of C# - NetConf Edition by Paulo Morgado
NetPonto - The Future Of C# - NetConf EditionNetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf Edition
Paulo Morgado234 views
Tuga IT 2018 Summer Edition - The Future of C# by Paulo Morgado
Tuga IT 2018 Summer Edition - The Future of C#Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#
Paulo Morgado469 views
Unit 5 Foc by JAYA
Unit 5 FocUnit 5 Foc
Unit 5 Foc
JAYA2.1K views
Hierarchical free monads and software design in fp by Alexander Granin
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fp
Alexander Granin161 views
Sparse Matrix and Polynomial by Aroosa Rajput
Sparse Matrix and PolynomialSparse Matrix and Polynomial
Sparse Matrix and Polynomial
Aroosa Rajput4.8K views
Analysis of Microsoft Code Contracts by PVS-Studio
Analysis of Microsoft Code ContractsAnalysis of Microsoft Code Contracts
Analysis of Microsoft Code Contracts
PVS-Studio445 views
JS Fest 2019. Anjana Vakil. Serverless Bebop by JSFestUA
JS Fest 2019. Anjana Vakil. Serverless BebopJS Fest 2019. Anjana Vakil. Serverless Bebop
JS Fest 2019. Anjana Vakil. Serverless Bebop
JSFestUA521 views
Debug Information And Where They Come From by Min-Yih Hsu
Debug Information And Where They Come FromDebug Information And Where They Come From
Debug Information And Where They Come From
Min-Yih Hsu126 views
Overview of Apache SystemML by Berthold Reinwald and Nakul Jindal by Arvind Surve
Overview of Apache SystemML by Berthold Reinwald and Nakul JindalOverview of Apache SystemML by Berthold Reinwald and Nakul Jindal
Overview of Apache SystemML by Berthold Reinwald and Nakul Jindal
Arvind Surve321 views

More from Alexander Granin

Concurrent applications with free monads and stm by
Concurrent applications with free monads and stmConcurrent applications with free monads and stm
Concurrent applications with free monads and stmAlexander Granin
208 views55 slides
Final tagless vs free monad by
Final tagless vs free monadFinal tagless vs free monad
Final tagless vs free monadAlexander Granin
158 views74 slides
О разработке десктопных приложений / About desktop development by
О разработке десктопных приложений / About desktop developmentО разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop developmentAlexander Granin
437 views22 slides
Принципы и практики разработки ПО 2 / Principles and practices of software de... by
Принципы и практики разработки ПО 2 / Principles and practices of software de...Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...Alexander Granin
133 views23 slides
Принципы и практики разработки ПО / Principles and practices of software deve... by
Принципы и практики разработки ПО / Principles and practices of software deve...Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...Alexander Granin
140 views30 slides
Закон Деметры / Demetra's law by
Закон Деметры / Demetra's lawЗакон Деметры / Demetra's law
Закон Деметры / Demetra's lawAlexander Granin
149 views17 slides

More from Alexander Granin(20)

Concurrent applications with free monads and stm by Alexander Granin
Concurrent applications with free monads and stmConcurrent applications with free monads and stm
Concurrent applications with free monads and stm
Alexander Granin208 views
О разработке десктопных приложений / About desktop development by Alexander Granin
О разработке десктопных приложений / About desktop developmentО разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop development
Alexander Granin437 views
Принципы и практики разработки ПО 2 / Principles and practices of software de... by Alexander Granin
Принципы и практики разработки ПО 2 / Principles and practices of software de...Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...
Alexander Granin133 views
Принципы и практики разработки ПО / Principles and practices of software deve... by Alexander Granin
Принципы и практики разработки ПО / Principles and practices of software deve...Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...
Alexander Granin140 views
Закон Деметры / Demetra's law by Alexander Granin
Закон Деметры / Demetra's lawЗакон Деметры / Demetra's law
Закон Деметры / Demetra's law
Alexander Granin149 views
GitHub - зеркало разработчика by Alexander Granin
GitHub - зеркало разработчикаGitHub - зеркало разработчика
GitHub - зеркало разработчика
Alexander Granin958 views
The Present and The Future of Functional Programming in C++ by Alexander Granin
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 Granin86 views
Functional programming in C++ LambdaNsk by Alexander Granin
Functional programming in C++ LambdaNskFunctional programming in C++ LambdaNsk
Functional programming in C++ LambdaNsk
Alexander Granin464 views
Transition graph using free monads and existentials by Alexander Granin
Transition graph using free monads and existentialsTransition graph using free monads and existentials
Transition graph using free monads and existentials
Alexander Granin473 views
Software transactional memory. pure functional approach by Alexander Granin
Software transactional memory. pure functional approachSoftware transactional memory. pure functional approach
Software transactional memory. pure functional approach
Alexander Granin968 views
Вы не понимаете ФП / You don't understand FP by Alexander Granin
Вы не понимаете ФП / You don't understand FPВы не понимаете ФП / You don't understand FP
Вы не понимаете ФП / You don't understand FP
Alexander Granin144 views
Functional "Life": parallel cellular automata and comonads by Alexander Granin
Functional "Life": parallel cellular automata and comonadsFunctional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonads
Alexander Granin885 views
Functional microscope - Lenses in C++ by Alexander Granin
Functional microscope - Lenses in C++Functional microscope - Lenses in C++
Functional microscope - Lenses in C++
Alexander Granin1.7K views
Дизайн больших приложений в ФП by Alexander Granin
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФП
Alexander Granin761 views
Линзы - комбинаторная манипуляция данными by Alexander Granin
Линзы - комбинаторная манипуляция даннымиЛинзы - комбинаторная манипуляция данными
Линзы - комбинаторная манипуляция данными
Alexander Granin389 views
Линзы - комбинаторная манипуляция данными (Dev2Dev) by Alexander Granin
Линзы - комбинаторная манипуляция данными (Dev2Dev)Линзы - комбинаторная манипуляция данными (Dev2Dev)
Линзы - комбинаторная манипуляция данными (Dev2Dev)
Alexander Granin483 views
Идиоматичный функциональный код by Alexander Granin
Идиоматичный функциональный кодИдиоматичный функциональный код
Идиоматичный функциональный код
Alexander Granin814 views
Функционально декларативный дизайн на C++ by Alexander Granin
Функционально декларативный дизайн на C++Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++
Alexander Granin1K views

Recently uploaded

LAVADORA ROLO.docx by
LAVADORA ROLO.docxLAVADORA ROLO.docx
LAVADORA ROLO.docxSamuelRamirez83524
7 views1 slide
Software testing company in India.pptx by
Software testing company in India.pptxSoftware testing company in India.pptx
Software testing company in India.pptxSakshiPatel82
7 views9 slides
DSD-INT 2023 Delft3D FM Suite 2024.01 2D3D - New features + Improvements - Ge... by
DSD-INT 2023 Delft3D FM Suite 2024.01 2D3D - New features + Improvements - Ge...DSD-INT 2023 Delft3D FM Suite 2024.01 2D3D - New features + Improvements - Ge...
DSD-INT 2023 Delft3D FM Suite 2024.01 2D3D - New features + Improvements - Ge...Deltares
17 views12 slides
Neo4j y GenAI by
Neo4j y GenAI Neo4j y GenAI
Neo4j y GenAI Neo4j
45 views41 slides
Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ... by
Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ...Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ...
Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ...Donato Onofri
773 views34 slides
DSD-INT 2023 The Danube Hazardous Substances Model - Kovacs by
DSD-INT 2023 The Danube Hazardous Substances Model - KovacsDSD-INT 2023 The Danube Hazardous Substances Model - Kovacs
DSD-INT 2023 The Danube Hazardous Substances Model - KovacsDeltares
8 views17 slides

Recently uploaded(20)

Software testing company in India.pptx by SakshiPatel82
Software testing company in India.pptxSoftware testing company in India.pptx
Software testing company in India.pptx
SakshiPatel827 views
DSD-INT 2023 Delft3D FM Suite 2024.01 2D3D - New features + Improvements - Ge... by Deltares
DSD-INT 2023 Delft3D FM Suite 2024.01 2D3D - New features + Improvements - Ge...DSD-INT 2023 Delft3D FM Suite 2024.01 2D3D - New features + Improvements - Ge...
DSD-INT 2023 Delft3D FM Suite 2024.01 2D3D - New features + Improvements - Ge...
Deltares17 views
Neo4j y GenAI by Neo4j
Neo4j y GenAI Neo4j y GenAI
Neo4j y GenAI
Neo4j45 views
Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ... by Donato Onofri
Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ...Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ...
Unmasking the Dark Art of Vectored Exception Handling: Bypassing XDR and EDR ...
Donato Onofri773 views
DSD-INT 2023 The Danube Hazardous Substances Model - Kovacs by Deltares
DSD-INT 2023 The Danube Hazardous Substances Model - KovacsDSD-INT 2023 The Danube Hazardous Substances Model - Kovacs
DSD-INT 2023 The Danube Hazardous Substances Model - Kovacs
Deltares8 views
MariaDB stored procedures and why they should be improved by Federico Razzoli
MariaDB stored procedures and why they should be improvedMariaDB stored procedures and why they should be improved
MariaDB stored procedures and why they should be improved
Headless JS UG Presentation.pptx by Jack Spektor
Headless JS UG Presentation.pptxHeadless JS UG Presentation.pptx
Headless JS UG Presentation.pptx
Jack Spektor7 views
DSD-INT 2023 Leveraging the results of a 3D hydrodynamic model to improve the... by Deltares
DSD-INT 2023 Leveraging the results of a 3D hydrodynamic model to improve the...DSD-INT 2023 Leveraging the results of a 3D hydrodynamic model to improve the...
DSD-INT 2023 Leveraging the results of a 3D hydrodynamic model to improve the...
Deltares6 views
El Arte de lo Possible by Neo4j
El Arte de lo PossibleEl Arte de lo Possible
El Arte de lo Possible
Neo4j39 views
DSD-INT 2023 Simulating a falling apron in Delft3D 4 - Engineering Practice -... by Deltares
DSD-INT 2023 Simulating a falling apron in Delft3D 4 - Engineering Practice -...DSD-INT 2023 Simulating a falling apron in Delft3D 4 - Engineering Practice -...
DSD-INT 2023 Simulating a falling apron in Delft3D 4 - Engineering Practice -...
Deltares6 views
DSD-INT 2023 Simulation of Coastal Hydrodynamics and Water Quality in Hong Ko... by Deltares
DSD-INT 2023 Simulation of Coastal Hydrodynamics and Water Quality in Hong Ko...DSD-INT 2023 Simulation of Coastal Hydrodynamics and Water Quality in Hong Ko...
DSD-INT 2023 Simulation of Coastal Hydrodynamics and Water Quality in Hong Ko...
Deltares12 views
A first look at MariaDB 11.x features and ideas on how to use them by Federico Razzoli
A first look at MariaDB 11.x features and ideas on how to use themA first look at MariaDB 11.x features and ideas on how to use them
A first look at MariaDB 11.x features and ideas on how to use them
Federico Razzoli45 views
Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI... by Marc Müller
Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI...Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI...
Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI...
Marc Müller37 views
Roadmap y Novedades de producto by Neo4j
Roadmap y Novedades de productoRoadmap y Novedades de producto
Roadmap y Novedades de producto
Neo4j50 views
Cycleops - Automate deployments on top of bare metal.pptx by Thanassis Parathyras
Cycleops - Automate deployments on top of bare metal.pptxCycleops - Automate deployments on top of bare metal.pptx
Cycleops - Automate deployments on top of bare metal.pptx

Monadic parsers in C++

  • 3. С++ Siberia 2019, Keynote The Present and the Future of Functional Programming in C++ С++ Russia 2018 Functional Approach to Software Transactional Memory in C++ С++ Russia 2016 Functional “Life”: Parallel Cellular Automata and Comonads in C++ С++ Siberia 2015 Functional Microscope: Lenses in C++ С++ User Group 2014 Functional and Declarative Design in C++ 3
  • 4. struct Presentation { Introduction Parsing and Backus-Naur form boost::spirit (qi) cpp_parsec_free Monadic parsers State & context-sensitive grammars Conclusion }; 4
  • 5. age integer first name string last name string salary float employee {35, “Jane”, “Street”, 54321} struct Employee { int age; string firstName; string lastName; double salary; }; Parsing 5
  • 6. employee ::= "employee" spaces "{" spaces age "," spaces firstName "," spaces lastName "," spaces salary spaces "}" Backus-Naur Form quotedString ::= '"' string '"' age ::= integer firstName ::= quotedString lastName ::= quotedString salary ::= double 6
  • 8. quoted_string %= lexeme['"' >> +(char_ - '"') >> '"']; start %= lit("employee") >> '{' >> int_ >> ',' >> quoted_string >> ',' >> quoted_string >> ',' >> double_ >> '}'; } 8
  • 9. quoted_string %= lexeme['"' >> +(char_ - '"') >> '"']; start %= lit("employee") >> '{' >> int_ >> ',' >> quoted_string >> ',' >> quoted_string >> ',' >> double_ >> '}'; } qi::rule<Iterator, string(), ascii::space_type> quoted_string; qi::rule<Iterator, employee(), ascii::space_type> start; 9
  • 10. template <typename Iterator> struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>{ employee_parser() : employee_parser::base_type(start) { quoted_string %= lexeme['"' >> +(char_ - '"') >> '"']; start %= lit("employee") >> '{' >> int_ >> ',' >> quoted_string >> ',' >> quoted_string >> ',' >> double_ >> '}'; } qi::rule<Iterator, string(), ascii::space_type> quoted_string; qi::rule<Iterator, employee(), ascii::space_type> start; }; 10
  • 11. template <typename Iterator> struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>{ employee_parser() : employee_parser::base_type(start) { quoted_string %= lexeme['"' >> +(char_ - '"') >> '"']; start %= lit("employee") >> '{' >> int_ >> ',' >> quoted_string >> ',' >> quoted_string >> ',' >> double_ >> '}'; } qi::rule<Iterator, string(), ascii::space_type> quoted_string; qi::rule<Iterator, employee(), ascii::space_type> start; }; 11
  • 12. 12
  • 14. ParserT<Employee> employee = app<Employee, int, string, string, double>( mkEmployee, prefix >> intP, comma >> quotedString, comma >> quotedString, comma >> (doubleP << postfix)); 14
  • 15. ParserT<Employee> employee = app<Employee, int, string, string, double>( mkEmployee, prefix >> intP, comma >> quotedString, comma >> quotedString, comma >> (doubleP << postfix)); auto prefix = lit("employee") >> between(spaces, symbol('{')); auto postfix = between(spaces, symbol('}')); auto comma = symbol(',') >> spaces; auto mkEmployee = [](int a, const string& sn, const string& fn, double s) { return Employee {a, sn, fn, s}; }; 15
  • 16. auto s = "employee {35, “Jane”, “Street”, 54321}"; ParserResult<Employee> result = parse(employee, s); 16
  • 17. auto s = "employee {35, “Jane”, “Street”, 54321}"; ParserResult<Employee> result = parse(employee, s); if (isLeft(result)) { std::cout << "Parse error: " << getError(result).message; } else { Employee employee = getParsed(result); } 17
  • 19. ParserT<int> intP; // integer number ParserT<double> doubleP; // double precision float ParserT<Char> digit; // 0..9 ParserT<Char> lower; // a..z ParserT<Char> upper; // A..Z ParserT<Char> letter; // a..z A..Z ParserT<Char> alphaNum; // 0..9 a..z A..Z ParserT<Char> symbol(Char ch); // symbol ParserT<string> lit(const string&); // string Basic parsers 19
  • 20. template <typename A, typename B> ParserT<A> fst(const ParserT<A>& p1, const ParserT<B>& p2); template <typename A, typename B> ParserT<B> snd(const ParserT<A>& p1, const ParserT<B>& p2); Parser combinators 20
  • 21. template <typename A, typename B> ParserT<A> fst(const ParserT<A>& p1, const ParserT<B>& p2); template <typename A, typename B> ParserT<B> snd(const ParserT<A>& p1, const ParserT<B>& p2); // fst template <typename A, typename B> ParserT<A> operator<< (const ParserT<A>& l, const ParserT<B>& r); // snd template <typename A, typename B> ParserT<B> operator>> (const ParserT<A>& l, const ParserT<B>& r); Parser combinators 21
  • 22. ParserT<string> helloWorld = snd(lit("Hello"), snd(symbol(' '), lit("world"))); ParserT<string> helloWorld = lit("Hello") >> symbol(' ') >> lit("world"); Parsing “Hello world” 22
  • 23. template <typename A> ParserT<Many<A>> many(const ParserT<A>& p); // 0 or many template <typename A> ParserT<Many<A>> many1(const ParserT<A>& p); // 1 or many template <typename A, typename B> ParserT<B> between(const ParserT<A>& bracketP, // between const ParserT<B>& p); More combinators 23
  • 24. template <typename A> ParserT<A> alt(const ParserT<A>& l, const ParserT<A>& r); template <typename A> ParserT<A> operator| (const ParserT<A>& l, const ParserT<A>& r); Alternative 24
  • 25. template <typename A> ParserT<A> alt(const ParserT<A>& l, const ParserT<A>& r); template <typename A> ParserT<A> operator| (const ParserT<A>& l, const ParserT<A>& r); ParserT<string> boolean = alt(lit("true"), lit("false")); ParserT<string> currency = lit("EUR") | lit("USD") | lit("GBP"); Alternative 25
  • 27. Functor fmap :: (A -> B) -> ParserT<A> -> ParserT<B> Applicative app :: (A -> B -> C) -> ParserT<A> -> ParserT<B> -> ParserT<C> Monad bind :: ParserT<A> -> (A -> ParserT<B>) 27
  • 28. fmap :: (A -> B) -> ParserT<A> -> ParserT<B> template <typename A, typename B> ParserT<B> fmap(const function<B(A)>& f, const ParserT<A>& p); Functor 28
  • 29. fmap :: (A -> B) -> ParserT<A> -> ParserT<B> template <typename A, typename B> ParserT<B> fmap(const function<B(A)>& f, const ParserT<A>& p); ParserT<string> strBoolean = lit("true") | lit("false"); Functor 29
  • 30. fmap :: (A -> B) -> ParserT<A> -> ParserT<B> template <typename A, typename B> ParserT<B> fmap(const function<B(A)>& f, const ParserT<A>& p); ParserT<string> strBoolean = lit("true") | lit("false"); ParserT<bool> boolean = fmap<string, bool>(f, strBoolean); function<bool(string)> f = [](const string& s) { return s == "true"; }; Functor 30
  • 31. Functor fmap :: (A -> B) -> ParserT<A> -> ParserT<B> Applicative app :: (A -> B -> C) -> ParserT<A> -> ParserT<B> -> ParserT<C> Monad bind :: ParserT<A> -> (A -> ParserT<B>) 31
  • 32. app :: (A -> B -> C) -> ParserT<A> -> ParserT<B> -> ParserT<C> template <typename A, typename B, typename C> ParserT<C> app(const function<C(A, B)>& f, const ParserT<A>& a, const ParserT<B>& b); Applicative 32
  • 33. app :: (A -> B -> C) -> ParserT<A> -> ParserT<B> -> ParserT<C> template <typename A, typename B, typename C> ParserT<C> app(const function<C(A, B)>& f, const ParserT<A>& a, const ParserT<B>& b); ParserT<string> helloUsername = app<string, string>( mkHello, letters, spaces >> letters); string mkHello = [](const string& firstName, const string& secondName) { return string("Hello, ") + firstName + " " + secondName + "!"; }; Applicative 33
  • 34. ParserT<Value> value = app(mkValue, intP | doubleP); Applicative is combinable 34
  • 35. ParserT<Value> value = app(mkValue, intP | doubleP); ParserT<BinOp> binOp = app(mkBinOp, symbol('+') | symbol('-') | symbol('*') | symbol('/')); Applicative is combinable 35
  • 36. ParserT<Value> value = app(mkValue, intP | doubleP); ParserT<BinOp> binOp = app(mkBinOp, symbol('+') | symbol('-') | symbol('*') | symbol('/')); ParserT<FuncArgs> funcArgs = app(mkFuncArgs, expr, opt(symbol(',') >> funcArgs)); Applicative is combinable 36
  • 37. ParserT<Value> value = app(mkValue, intP | doubleP); ParserT<BinOp> binOp = app(mkBinOp, symbol('+') | symbol('-') | symbol('*') | symbol('/')); ParserT<FuncArgs> funcArgs = app(mkFuncArgs, expr, opt(symbol(',') >> funcArgs)); ParserT<FuncCall> funcCall = app(mkFuncCall, identifier, between('(', ')', funcArgs)); Applicative is combinable 37
  • 38. ParserT<Value> value = app(mkValue, intP | doubleP); ParserT<BinOp> binOp = app(mkBinOp, symbol('+') | symbol('-') | symbol('*') | symbol('/')); ParserT<FuncArgs> funcArgs = app(mkFuncArgs, expr, opt(symbol(',') >> funcArgs)); ParserT<FuncCall> funcCall = app(mkFuncCall, identifier, between('(', ')', funcArgs)); ParserT<BinExpr> binExpr = app(mkBinExpr, expr, binOp, expr); Applicative is combinable 38
  • 39. ParserT<Value> value = app(mkValue, intP | doubleP); ParserT<BinOp> binOp = app(mkBinOp, symbol('+') | symbol('-') | symbol('*') | symbol('/')); ParserT<FuncArgs> funcArgs = app(mkFuncArgs, expr, opt(symbol(',') >> funcArgs)); ParserT<FuncCall> funcCall = app(mkFuncCall, identifier, between('(', ')', funcArgs)); ParserT<BinExpr> binExpr = app(mkBinExpr, expr, binOp, expr); ParserT<Expr> expr = app(mkExpr, binExpr | funcCall | value); Applicative is combinable 39
  • 40. Functor fmap :: (A -> B) -> ParserT<A> -> ParserT<B> Applicative app :: (A -> B -> C) -> ParserT<A> -> ParserT<B> -> ParserT<B> Monad bind :: ParserT<A> -> (A -> ParserT<B>) 40
  • 41. template <typename A> ParserT<A> pure(const A& a); template <typename A, typename B> ParserT<B> bind( const ParserT<A>& ma, const function<ParserT<B>(A)>& f); ParserT monad 41
  • 42. ParserT<string> helloUsername = bind<string, string>(letters, [=](auto firstName) { return bind<string, string>(spaces, [=](auto) { return bind<string, string>(letters, [=](auto lastName) { return pure<string>(mkHello(firstName, lastName)); }); }); }); ParserT<string> helloUsername = bind<string, string>(letters, [=](auto firstName) { return bind<string, string>(spaces, [=](auto) { return bind<string, string>(letters, [=](auto lastName) { return pure<string>(mkHello(firstName, lastName)); }); }); }); Monadic binding 42
  • 43. ParserT<string> helloUsername = bind<string, string>(letters, [=](auto firstName) { return bind<string, string>(spaces, [=](auto) { return bind<string, string>(letters, [=](auto lastName) { return pure<string>(mkHello(firstName, lastName)); }); }); }); ParserT<string> helloUsername = bind<string, string>(letters, [=](auto firstName) { return bind<string, string>(spaces, [=](auto) { return bind<string, string>(letters, [=](auto lastName) { return pure<string>(mkHello(firstName, lastName)); }); }); }); Monadic binding, reformatted 43
  • 44. ParserT<string> helloUsername = do { auto firstName <- letters; auto _ <- spaces; auto lastName <- letters; return pure<string>(mkHello(firstName, lastName)); }; Dear Santa, I was a good boy last year. Can I have?.. 44
  • 46. age integer first name string last name string salary float employee {35, “Jane”, “Street”, 54321} address {35, “Jane”, “Street”, 54321} house integer title string post index integer type string 46
  • 47. struct Employee { int age; string firstName; string lastName; double salary; }; 47 struct Address { int house; string title; string name; int postIndex; }; Algebraic Data Type
  • 48. struct Employee { int age; string firstName; string lastName; double salary; }; 48 struct Address { int house; string title; string name; int postIndex; }; using LogEntry = std::variant<Employee, Address>; Algebraic Data Type
  • 49. struct Employee { int age; string firstName; string lastName; double salary; }; 49 struct Address { int house; string title; string name; int postIndex; }; using LogEntry = std::variant<Employee, Address>; function<LogEntry(int a, const string& fn, const string& ln, double s)> mkEmployeeEntry; function<LogEntry(int h, const string& ttl, const string& n, int idx)> mkAddressEntry; Algebraic Data Type
  • 50. struct Config { string currentEntry; }; ParserT<Config, string> logToken = lit("employee") | lit("address"); ParserT<Config, Unit> setEntry = bind<string, Unit>( logToken, [](const string& s) { return putSt(Config { s }); }); Putting state 50
  • 51. struct Config { string currentEntry; }; ParserT<Config, string> logToken = lit("employee") | lit("address"); ParserT<Config, Unit> setEntry = bind<string, Unit>( logToken, [](const string& s) { return putSt(Config { s }); }); Putting state 51
  • 52. ParserT<Config, LogEntry> logEntry = bind<Config, LogEntry>(getSt, [=](Config cfg) { if (cfg.currentEntry == "employee") return fmap(mkEmployeeEntry, employeeParser); return fmap(mkAddressEntry, addressParser); }); Getting state 52
  • 53. ParserT<Config, LogEntry> logEntry = bind<Config, LogEntry>(getSt, [=](Config cfg) { if (cfg.currentEntry == "employee") return fmap(mkEmployeeEntry, employeeParser); return fmap(mkAddressEntry, addressParser); }); Getting state 53
  • 55. Monadic parser combinators ● Monad: do-notation, bind, when, unless, sequence, mapM, guard ● Applicative: app, pure ● Alternative: alt, operator| ● Functor: fmap ● Time travelling: lookForward, lookBackward ● State handling: getSt, putSt ● Error handling: tryP, safeP, onFail, onSuccess, failWith 55
  • 56. 56 GitHub List: Functional Programming in C++ https://github.com/graninas/cpp_functional_programming�� ● Books ● Articles ● Papers ● Talks ● QA ● Libraries ● Showcase projects
  • 57. Thanks for watching! Alexander Granin graninas@gmail.com Twitter: @graninas C++ Russia 2019, Moscow 57