├── .gitignore ├── README.md ├── cxxnow2014_expected.tex ├── cxxnow2014_expected_monads.tex ├── expected-c++now-proposal.tex ├── expected-meeting-c++-proposal.tex ├── expected-proposal.tex └── references.bib /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.aux 3 | 4 | *.bib 5 | 6 | *.log 7 | 8 | *.out 9 | 10 | *.gz 11 | 12 | expected-proposal.pdf 13 | 14 | *.toc 15 | 16 | .project 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | !!! WARINING !!! 2 | 3 | This repository is abandoned. 4 | 5 | This proposal has moved to this repository https://github.com/viboes/std-make/blob/master/doc/proposal/expected/ and https://github.com/viboes/std-make/tree/master/doc/proposal/expected. 6 | 7 | Please, add any issues in the new repository. 8 | 9 | !!! WARINING !!! 10 | 11 | 12 | std-expected-proposal 13 | ===================== 14 | 15 | On going C++ standard proposal for a expected class. 16 | 17 | Last uploaded DRAFT 18 | ------------------- 19 | See http://www.hyc.io/boost/expected-proposal.pdf 20 | 21 | Reference implementation 22 | ------------------------ 23 | See https://github.com/ptal/Boost.Expected/ for a reference implementation. 24 | -------------------------------------------------------------------------------- /cxxnow2014_expected.tex: -------------------------------------------------------------------------------- 1 | \documentclass[xcolor=dvipsnames]{beamer} 2 | 3 | \usepackage[utf8]{inputenc} 4 | \usepackage[english]{babel} 5 | \usepackage{url} 6 | \usepackage{lmodern} 7 | \usepackage{listings} 8 | \usepackage{graphicx} 9 | \usepackage{xcolor} 10 | \usepackage{textcomp} 11 | \usepackage{hyperref} 12 | \usepackage{subcaption} 13 | \usepackage[T1]{fontenc} 14 | 15 | \usepackage{color} 16 | 17 | \definecolor{dkgreen}{rgb}{0,0.6,0} 18 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 19 | \definecolor{mauve}{rgb}{0.58,0,0.82} 20 | 21 | \lstset{ 22 | language=c++, % the language of the code 23 | basicstyle=\footnotesize, % the size of the fonts that are used for the code 24 | numbers=left, % where to put the line-numbers 25 | numberstyle=\tiny\color{gray}, % the style that is used for the line-numbers 26 | stepnumber=1, % the step between two line-numbers. If it's 1, each line 27 | % will be numbered 28 | numbersep=5pt, % how far the line-numbers are from the code 29 | backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color} 30 | showtabs=false, % show tabs within strings adding particular underscores 31 | frame=single, % adds a frame around the code 32 | rulecolor=\color{black}, % if not set, the frame-color may be changed on line-breaks within not-black text (e.g. comments (green here)) 33 | tabsize=2, % sets default tabsize to 2 spaces 34 | captionpos=b, % sets the caption-position to bottom 35 | breaklines=true, % sets automatic line breaking 36 | breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace 37 | title=\lstname, % show the filename of files included with \lstinputlisting; 38 | % also try caption instead of title 39 | keywordstyle=\color{blue}, % keyword style 40 | commentstyle=\color{dkgreen}, % comment style 41 | stringstyle=\color{mauve}, % string literal style 42 | morekeywords={expect, await, constexpr, explicit} 43 | } 44 | 45 | \newcommand{\cpp}[1]{\lstinline{#1}} 46 | 47 | \setbeamertemplate{footline}{\hspace*{.5cm}\scriptsize{\insertauthor\hspace*{50pt} \hfill\insertframenumber\hspace*{.5cm}}} 48 | 49 | \setbeamertemplate{section in toc}{% 50 | \textcolor{MidnightBlue}{$\blacktriangleright$ \inserttocsection} 51 | } 52 | 53 | \usecolortheme{seahorse} 54 | \usecolortheme{rose} 55 | \useoutertheme{infolines} 56 | 57 | \usecolortheme[named=SkyBlue]{structure} 58 | \setbeamercolor{block title}{fg=MidnightBlue} 59 | 60 | \AtBeginSection[] 61 | { 62 | \begin{frame}{Content} 63 | \tableofcontents[currentsection,hideothersubsections] 64 | \end{frame} 65 | } 66 | 67 | \title{\textsc{Expected}: Exception-friendly Error Monad} 68 | \subtitle{C++Now 2014} 69 | \author[\textsc{Vicente Botet}]{Vicente \textsc{Botet Escriba} \texttt{vicente.botet@wanadoo.fr}} 70 | \institute[Alcatel-Lucent]{Alcatel-Lucent International-Lannion} 71 | \date[]{2014, May 16} 72 | 73 | \begin{document} 74 | \maketitle 75 | 76 | \section{Introduction} 77 | %%%%%%%%%% 78 | 79 | \subsection{About me} 80 | 81 | \begin{frame} 82 | \frametitle{About Vicente Botet Escriba} 83 | 84 | % \begin{figure}[p] 85 | % \centering 86 | % \begin{subfigure}[b]{0.3\textwidth} 87 | % \includegraphics[scale=0.3]{images/vicente_botet.png} 88 | % \end{subfigure} 89 | % \qquad \qquad \quad 90 | % \begin{subfigure}[b]{0.3\textwidth} 91 | % \includegraphics[scale=0.3]{images/alu.jpg} 92 | % \end{subfigure} 93 | % \end{figure} 94 | 95 | \begin{itemize} 96 | \item Spanish. 97 | \item Work for Alcatel-Lucent International in Lannion - France. 98 | \item Interest in software engineering, language design, concurrency and STM. 99 | \end{itemize} 100 | 101 | \begin{block}{Open-source involvement} 102 | \begin{itemize} 103 | \item \textbf{Boost C++ library} Co-author and maintainer of Boost.Ratio, Boost.Chrono, Boost.Thread and some utilities in Boost.Utility. 104 | \item \textbf{Toward Boost C++ library} author of a lot of unfinished prototypes. 105 | \end{itemize} 106 | \end{block} 107 | \end{frame} 108 | 109 | \subsection{About Boost.Expected} 110 | %%%%%%%%%%%% 111 | \begin{frame} 112 | \frametitle{About Boost.Expected} 113 | 114 | \begin{itemize} 115 | \item Original idea of Andrei Alexandrescu (Systematic Error Handling in C++). 116 | \item Interface based on the new \cpp{std::experimental::optional} type. 117 | \item Extended to conform to the error monad concept. 118 | \item We are currently working on a C++ standard proposal that we expect to be ready for Rapperswil. 119 | \item Once the interface would be more stable we will propose it for review to Boost. 120 | \end{itemize} 121 | \end{frame} 122 | 123 | \begin{frame} 124 | \frametitle{About Boost.Expected} 125 | 126 | \begin{itemize} 127 | \item The project born as a proposal the authors made for GSoC 2013. 128 | \item Pierre Talbot is the student working on it with me. 129 | \end{itemize} 130 | 131 | \begin{block}{Links} 132 | \begin{itemize} 133 | \item Git repository : https://github.com/ptal/Boost.Expected 134 | \item C++ draft proposal : http://www.hyc.io/boost/expected-proposal.pdf 135 | \end{itemize} 136 | \end{block} 137 | \end{frame} 138 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 139 | 140 | \begin{frame}[fragile] 141 | \frametitle{Overview} 142 | 143 | \cpp{expected} answer to the question "do you contain a value of type \cpp{T} or an error of type \cpp{E}?". 144 | 145 | \begin{lstlisting} 146 | template 147 | class expected { 148 | bool has_value_; 149 | union{ 150 | T val_; 151 | E err_; 152 | }; 153 | }; 154 | \end{lstlisting} 155 | 156 | \begin{itemize} 157 | \item \cpp{expected = T + unexpected_type} 158 | \item \cpp{T != unexpected_type} 159 | \item We want that \cpp{expected} behaves as \cpp{T}. 160 | \item \cpp{expected = Expected} 161 | \end{itemize} 162 | 163 | \end{frame} 164 | 165 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 166 | \begin{frame}[fragile] 167 | \frametitle{How to create an expected object} 168 | 169 | \begin{itemize} 170 | \item Valued. 171 | \end{itemize} 172 | 173 | \begin{lstlisting} 174 | expected ei = make_expected(1); 175 | expected ej{2}; // alternative syntax 176 | expected ek = ej; // ek has value 2 177 | 178 | expected el{in_place, "arg"}; 179 | expected el{expect, "arg"}; 180 | // calls MoveOnly{"arg"} in place 181 | \end{lstlisting} 182 | 183 | \end{frame} 184 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 185 | \begin{frame}[fragile] 186 | \frametitle{How to create an unexpected object} 187 | 188 | \begin{itemize} 189 | \item Unexpected. 190 | \end{itemize} 191 | 192 | \begin{lstlisting} 193 | expected ek = make_unexpected(errc::invalid); 194 | 195 | expected em{unexpect, "arg"}; 196 | // unexpected value, calls string{"arg"} in place 197 | 198 | expected e; // e is unexpected... 199 | ei = {}; // reset to unexpected 200 | \end{lstlisting} 201 | 202 | \end{frame} 203 | 204 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 205 | \begin{frame}[fragile] 206 | \frametitle{Observing an expected object} 207 | 208 | \begin{itemize} 209 | \item Explicit conversion to bool. 210 | \item \cpp{operator*()} narrow contract 211 | \end{itemize} 212 | 213 | \begin{lstlisting} 214 | if (expected ch = readNextChar()) { 215 | process_char(*ch); 216 | } 217 | \end{lstlisting} 218 | 219 | \begin{itemize} 220 | \item \cpp{value()} wide contract 221 | \end{itemize} 222 | 223 | \begin{lstlisting} 224 | expected ei = str2int(s); 225 | try { 226 | process_int(ei.value()); 227 | } catch(bad_expected_access const&) { 228 | std::cout << "this was not a number"; 229 | } 230 | \end{lstlisting} 231 | 232 | \end{frame} 233 | 234 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 235 | \section{Expected Library by Example} 236 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 237 | \subsection{\cpp{safe_divide}} 238 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 239 | \begin{frame}[fragile] 240 | \frametitle{safe\_divide exception-based style} 241 | 242 | \begin{lstlisting} 243 | struct DivideByZero: public std::exception {...}; 244 | \end{lstlisting} 245 | 246 | \begin{lstlisting} 247 | int safe_divide(int i, int j) 248 | { 249 | if (j==0) throw DivideByZero(); 250 | else return i / j; 251 | } 252 | \end{lstlisting} 253 | \end{frame} 254 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 255 | \begin{frame}[fragile] 256 | \frametitle{safe\_divide Expected-based style} 257 | 258 | \begin{lstlisting} 259 | Expected safe_divide(int i, int j) 260 | { 261 | if (j==0) return Expected::from_error(DivideByZero()); 262 | else return Expected(i / j); 263 | } 264 | \end{lstlisting} 265 | \begin{itemize} 266 | \item (3,4) redondant use of \cpp{Expected}. 267 | \end{itemize} 268 | 269 | \end{frame} 270 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 271 | \begin{frame}[fragile] 272 | \frametitle{safe\_divide expected-based style} 273 | 274 | Using \cpp{boost::expected} to carry the error condition. 275 | 276 | \begin{lstlisting} 277 | expected safe_divide(int i, int j) 278 | { 279 | if (j==0) return make_unexpected(DivideByZero()); 280 | else return i / j; 281 | } 282 | \end{lstlisting} 283 | 284 | \begin{itemize} 285 | \item (3) uses implicit conversion from \cpp{unexpected_type} to \cpp{expected}. 286 | \item (4) uses implicit conversion from \cpp{T} to \cpp{expected}. 287 | \end{itemize} 288 | 289 | \begin{itemize} 290 | \item The advantages are that we have a clean way to fail without using the exception machinery, and we can give precise information about why it failed as well. 291 | \item The liability is that this function is going to be tedious to use. 292 | \end{itemize} 293 | 294 | \end{frame} 295 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 296 | \begin{frame}[fragile] 297 | \frametitle{safe\_divide expected-style - getting the value or an exception} 298 | 299 | \begin{itemize} 300 | \item The caller obtains the stored value using the member \cpp{value()} function. 301 | \end{itemize} 302 | 303 | \begin{lstlisting} 304 | auto x = safe_divide(i,j).value(); // throw on error 305 | \end{lstlisting} 306 | 307 | \begin{itemize} 308 | \item The caller can also store the expected value and check if a value is stored using the bool conversion function. 309 | \end{itemize} 310 | 311 | \begin{lstlisting} 312 | auto x = safe_divide(i,j); // won't throw 313 | if (! x) 314 | int i = x.value(); // just "re"throw the stored exception 315 | \end{lstlisting} 316 | 317 | \end{frame} 318 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 319 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 320 | \begin{frame}[fragile] 321 | \frametitle{\cpp{i + j/k} expected-style - getting the value when available} 322 | 323 | \begin{itemize} 324 | \item When the user knows that there is a value it can use the narrowed contract \cpp{operator*()}. 325 | \end{itemize} 326 | 327 | \begin{lstlisting} 328 | expected f1(int i, int j, int k) 329 | { 330 | auto q = safe_divide(j, k) 331 | if(q) return i + *q; 332 | else return make_unexpected(q); 333 | } 334 | \end{lstlisting} 335 | 336 | \end{frame} 337 | \subsection{\cpp{i + j/k}} 338 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 339 | \begin{frame}[fragile] 340 | \frametitle{\cpp{i + j/k} - functional style} 341 | 342 | \begin{lstlisting} 343 | expected f1(int i, int j, int k) 344 | { 345 | return safe_divide(j, k).fmap([i](int q){return i + q;}); 346 | } 347 | \end{lstlisting} 348 | 349 | \cpp{fmap} calls the provided function if expected contains a value and wraps the result, otherwise it forwards the error to the callee. 350 | 351 | Alternative using an existing functor. 352 | 353 | \begin{lstlisting} 354 | expected f1(int i, int j, int k) 355 | { 356 | return safe_divide(j, k).fmap(bind(add, i, _1))); 357 | } 358 | \end{lstlisting} 359 | \end{frame} 360 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 361 | \begin{frame}[fragile] 362 | \frametitle{safe\_divide - exception-based Multiple error conditions} 363 | 364 | \begin{lstlisting} 365 | struct NotDivisible: public std::exception { 366 | int i, j; 367 | NotDivisible(int i, int j) : i(i), j(j) {} 368 | }; 369 | 370 | int safe_divide(int i, int j) { 371 | if (j == 0) throw DivideByZero(); 372 | if (i%j != 0) throw NotDivisible(i,j); 373 | else return i / j; 374 | } 375 | \end{lstlisting} 376 | 377 | \begin{lstlisting} 378 | T divide(T i, T j) { 379 | try { return safe_divide(i,j) } 380 | catch(NotDivisible& ex) { return ex.i/ex.j; } 381 | catch(...) { throw; } 382 | } 383 | \end{lstlisting} 384 | \end{frame} 385 | \subsection{\cpp{divide}} 386 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 387 | \begin{frame}[fragile] 388 | \frametitle{safe\_divide - expected-based Multiple error conditions} 389 | 390 | \begin{lstlisting} 391 | expected safe_divide(int i, int j) { 392 | if (j == 0) return make_unexpected(DivideByZero()); 393 | if (i%j != 0) return make_unexpected(NotDivisible(i,j)); 394 | else return i / j; 395 | } 396 | \end{lstlisting} 397 | 398 | \begin{lstlisting} 399 | expected divide(int i, int j) { 400 | auto e = safe_divide(i,j); 401 | if(e.has_exception()) return i/j; 402 | else return e; 403 | } 404 | \end{lstlisting} 405 | \end{frame} 406 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 407 | \begin{frame}[fragile] 408 | \frametitle{safe\_divide - expected-based Multiple error conditions} 409 | 410 | \begin{lstlisting} 411 | expected divide(int i, int j) { 412 | return safe_divide(i,j) 413 | .catch_exception([](auto &ex) 414 | return ex.i/ex.j; 415 | }); 416 | } 417 | \end{lstlisting} 418 | 419 | \end{frame} 420 | \subsection{\cpp{i/k + j/k}} 421 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 422 | \begin{frame}[fragile] 423 | \frametitle{\cpp{i/k + j/k} - scale} 424 | 425 | \begin{itemize} 426 | \item exception-based. 427 | \end{itemize} 428 | 429 | \begin{lstlisting} 430 | int f2(int i, int j, int k) { 431 | return safe_divide(i,k) + safe_divide(j,k); 432 | } 433 | \end{lstlisting} 434 | 435 | \begin{itemize} 436 | \item expected-based. 437 | \end{itemize} 438 | 439 | \begin{lstlisting} 440 | expected f2(int i, int j, int k) { 441 | auto q1 = safe_divide(i, k); 442 | if (!q1) return make_unexpected(q1); 443 | 444 | auto q2 = safe_divide(j, k); 445 | if (!q2) return make_unexpected(q2); 446 | 447 | return *q1 + *q2; 448 | } 449 | \end{lstlisting} 450 | 451 | \end{frame} 452 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 453 | \begin{frame}[fragile] 454 | \frametitle{\cpp{i/k + j/k} - scale} 455 | 456 | \begin{itemize} 457 | \item expected-based functional style. 458 | \end{itemize} 459 | 460 | \begin{lstlisting} 461 | expected f(int i, int j, int k) { 462 | return safe_divide(i, k).mbind([=](int q1) { 463 | return safe_divide(j,k).fmap([=](int q2) { 464 | return q1+q2; 465 | }); 466 | }); 467 | } 468 | \end{lstlisting} 469 | 470 | \cpp{mbind} calls the provided function if expected contains a value, otherwise it forwards the error to the callee. 471 | 472 | \end{frame} 473 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 474 | \begin{frame}[fragile] 475 | \frametitle{\cpp{i/k + j/k} - scale} 476 | 477 | \begin{lstlisting} 478 | auto add = [](int s1, int s2){ return s1+s2; }; 479 | expected f(int i, int j, int k){ 480 | return fmap(add, safe_divide(i, k), safe_divide(j, k)); 481 | } 482 | \end{lstlisting} 483 | 484 | The \cpp{fmap} non-member function calls the provided function if all the expected contains a value and wraps the result, otherwise it forwards the first error to the callee. 485 | 486 | \end{frame} 487 | \subsection{do-expression} 488 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 489 | \begin{frame}[fragile] 490 | \frametitle{language-like style - error propagation} 491 | Possible C++ language extension: Based on the Haskell do-expression. Something similar to the proposed \cpp{await} expression for futures. 492 | 493 | \begin{lstlisting} 494 | expected f2(int i, int j, int k) { 495 | return ( auto s1 <- safe_divide(i, k) : 496 | auto s2 <- safe_divide(j, k) : 497 | s1 + s2 498 | ); 499 | } 500 | \end{lstlisting} 501 | 502 | transformed in 503 | 504 | \begin{lstlisting} 505 | expected f2(int i, int j, int k) { 506 | return mbind(safe_divide(i, k),[&](auto s1) { 507 | return mbind(safe_divide(j, k),[&](auto s2) { 508 | return s1 + s2; 509 | }); 510 | }); 511 | } 512 | \end{lstlisting} 513 | \end{frame} 514 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 515 | \begin{frame}[fragile] 516 | \frametitle{\cpp{i/k + j/k} - DO-macro} 517 | 518 | \begin{lstlisting} 519 | expected f2(int i, int j, int k) { 520 | return DO ( 521 | ( s1, safe_divide(i, k) ) 522 | ( s2, safe_divide(j, k) ) 523 | s1 + s2 524 | ); 525 | } 526 | \end{lstlisting} 527 | 528 | \end{frame} 529 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 530 | \begin{frame}[fragile] 531 | \frametitle{\cpp{i/k + j/k} - EXPECT-macro} 532 | 533 | \begin{lstlisting} 534 | #define EXPECT(V, EXPR) \ 535 | auto BOOST_JOIN(_expected_,V) = EXPR; \ 536 | if (! BOOST_JOIN(_expected_,V)) 537 | return make_unexpected(BOOST_JOIN(_expected_,V).error()); \ 538 | auto V =*BOOST_JOIN(_expected_,V) 539 | \end{lstlisting} 540 | 541 | \begin{lstlisting} 542 | expected f2(int i, int j, int k) { 543 | EXPECT(s1, safe_divide(i, k) ); 544 | EXPECT(s2, safe_divide(j, k)); 545 | return s1 + s2; 546 | } 547 | \end{lstlisting} 548 | 549 | \end{frame} 550 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 551 | \subsection{getIntRange } 552 | %%%%%%%%%%%% 553 | 554 | \begin{frame}[fragile] 555 | \frametitle{getIntRange - exception based} 556 | 557 | Given 558 | \begin{lstlisting} 559 | int getInt(istream_range& r); 560 | void matchesString(std::string, istream_range& r); 561 | \end{lstlisting} 562 | 563 | \begin{lstlisting} 564 | pair getIntRange(istream_range& r) 565 | { 566 | auto f = getInt(r); 567 | matchesString("..", r); 568 | auto l = getInt(r); 569 | return make_pair(f, l); 570 | } 571 | \end{lstlisting} 572 | 573 | \end{frame} 574 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 575 | \begin{frame}[fragile] 576 | \frametitle{getIntRange - expect based} 577 | 578 | Given 579 | \begin{lstlisting} 580 | expected getInt(istream_range& r); 581 | expected matchesString(istream_range& r); 582 | \end{lstlisting} 583 | 584 | \begin{lstlisting} 585 | expected> getIntRange(istream_range& r) 586 | { 587 | return 588 | auto f <- getInt(r) : 589 | matchedString("..", r) : 590 | auto l <- getInt(r) : 591 | std::make_pair(f, l); 592 | } 593 | \end{lstlisting} 594 | 595 | \end{frame} 596 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 597 | \section{Behind the scenes} 598 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 599 | \subsection{Unexpected Type} 600 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 601 | \begin{frame}[fragile] 602 | \frametitle{class unexpected\_type} 603 | 604 | Between explicit and implicit conversion. 605 | 606 | Building an explicit type that is implicitly convertible to another type. 607 | 608 | E.g. \cpp{imaginary} is explicitly convertible from a \cpp{T} and \cpp{complex} could be implicitly convertible from \cpp{imaginary}. 609 | 610 | \begin{lstlisting} 611 | template 612 | class unexpected_type { 613 | public: 614 | unexpected_type() = delete; 615 | constexpr explicit unexpected_type(E e) 616 | : error_(e) {} 617 | constexpr E value() const { return error_; } 618 | }; 619 | \end{lstlisting} 620 | 621 | \end{frame} 622 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 623 | \begin{frame}[fragile] 624 | \frametitle{unexpected factories} 625 | 626 | \begin{lstlisting} 627 | template 628 | constexpr unexpected_type> make_unexpected(E v) { 629 | return unexpected_type> (ex); 630 | } 631 | 632 | unexpected_type<> 633 | make_unexpected_from_current_exception() { 634 | return unexpected_type<> (std::current_exception()); 635 | } 636 | 637 | template 638 | constexpr 639 | unexpected_type make_unexpected(expected v) { 640 | return unexpected_type(v.error()); 641 | } 642 | 643 | \end{lstlisting} 644 | \end{frame} 645 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 646 | \subsection{Expected Type} 647 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 648 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 649 | \subsubsection{Conversions} 650 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 651 | \begin{frame}[fragile] 652 | \frametitle{\cpp{expected} conversions from/to \cpp{E} and \cpp{unexpected_type}} 653 | 654 | \begin{itemize} 655 | \item \cpp{expected} is not convertible from \cpp{E} . 656 | \item \cpp{expected} is implicitly convertible from \cpp{unexpected_type} . 657 | \item The opposite is not true. Needs explicit function \cpp{get_unexpected()}. 658 | \end{itemize} 659 | 660 | \begin{lstlisting} 661 | template 662 | class expected { 663 | // ... 664 | constexpr expected(unexpected_type&& e); 665 | expected& operator=(unexpected_type&& e); 666 | 667 | // ... 668 | constexpr E const& error() const& noexcept; 669 | constexpr E& error() & noexcept; 670 | constexpr E&& error() && noexcept; 671 | constexpr unexpected_type get_unexpected() const&; 672 | constexpr unexpected_type get_unexpected() &&; 673 | }; 674 | \end{lstlisting} 675 | 676 | \end{frame} 677 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 678 | \begin{frame}[fragile] 679 | \frametitle{\cpp{expected} conversions from/to \cpp{unexpected_type}} 680 | 681 | \begin{itemize} 682 | \item \cpp{expected} is implicitly convertible from \cpp{unexpected_type} for any \cpp{E}. 683 | \end{itemize} 684 | 685 | \begin{lstlisting} 686 | template 687 | class expected { 688 | // ... 689 | constexpr expected(unexpected_type&& e); 690 | expected& operator=(unexpected_type&& e); 691 | template 692 | constexpr expected(unexpected_type&& e); 693 | template 694 | expected& operator=(unexpected_type&& e); 695 | 696 | // ... 697 | }; 698 | \end{lstlisting} 699 | 700 | \end{frame} 701 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 702 | \begin{frame}[fragile] 703 | \frametitle{\cpp{expected} conversions from/to \cpp{T}} 704 | 705 | \begin{itemize} 706 | \item \cpp{expected} is implicitly convertible from \cpp{T} . 707 | \item The opposite is not true. Needs explicit function \cpp{value()}. 708 | \end{itemize} 709 | 710 | \begin{lstlisting} 711 | template 712 | class expected { 713 | // ... 714 | constexpr expected(T const& v); 715 | constexpr expected(T&& v); 716 | expected& operator=(T&& v); 717 | 718 | constexpr T const& value() const&; 719 | constexpr T& value() &; 720 | constexpr T&& value() &&; 721 | 722 | }; 723 | \end{lstlisting} 724 | 725 | \end{frame} 726 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 727 | \subsubsection{Constructors} 728 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 729 | \begin{frame}[fragile] 730 | \frametitle{Default constructor} 731 | While \cpp{expected} is default constructible, there is no exception stored in. 732 | 733 | Alternatives: 734 | 735 | \begin{itemize} 736 | \item value() is undefined behavior if there is no exception stored or 737 | \item it throws a specific exception if there is no exception stored. 738 | \end{itemize} 739 | 740 | \end{frame} 741 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 742 | \subsubsection{Observers} 743 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 744 | \begin{frame}[fragile] 745 | \frametitle{\cpp{pointer-like}} 746 | 747 | \begin{lstlisting} 748 | template 749 | class expected { 750 | // ... 751 | constexpr explicit operator bool() const noexcept; 752 | 753 | constexpr T const& operator*() const& noexcept; 754 | constexpr T& operator*() & noexcept; 755 | constexpr T&& operator*() && noexcept; 756 | 757 | constexpr T const * operator->() const noexcept; 758 | constexpr T* operator*() noexcept; 759 | 760 | }; 761 | \end{lstlisting} 762 | 763 | \end{frame} 764 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 765 | \subsubsection{Monadic functions} 766 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 767 | \begin{frame}[fragile] 768 | \frametitle{Monadic functions} 769 | 770 | 771 | \begin{tabular}{|c|c|c|c|c|} 772 | \hline 773 | & Object & From & To & Result \\ 774 | \hline 775 | \textbf{fmap} & \cpp{M} & \cpp{T} & \cpp{U} & \cpp{M} \\ 776 | \hline 777 | \textbf{fmap} & \cpp{M} & \cpp{T} & \cpp{M} & \cpp{M>} \\ 778 | \hline 779 | \textbf{mbind} & \cpp{M} & \cpp{T} & \cpp{U} & \cpp{M} \\ 780 | \hline 781 | \textbf{mbind} & \cpp{M} & \cpp{T} & \cpp{M} & \cpp{M} \\ 782 | \hline 783 | \textbf{catch\_error} & \cpp{M} & \cpp{E} & \cpp{T} & \cpp{M} \\ 784 | \hline 785 | \textbf{catch\_error} & \cpp{M} & \cpp{E} & \cpp{M} & \cpp{M} \\ 786 | \hline 787 | \textbf{then} & \cpp{M} & \cpp{M} & \cpp{U} & \cpp{M} \\ 788 | \hline 789 | \textbf{then} & \cpp{M} & \cpp{M} & \cpp{M} & \cpp{M} \\ 790 | \hline 791 | \end{tabular} 792 | 793 | \end{frame} 794 | 795 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 796 | \begin{frame}[fragile] 797 | \frametitle{\cpp{fmap} member} 798 | 799 | \begin{lstlisting} 800 | template 801 | constexpr expected> 802 | expected::fmap(F&& f, 803 | REQUIRES( ! is_void_v> ) 804 | ) const 805 | { 806 | typedef expected> result_type; 807 | if (*this) return result_type(f(**this)); 808 | else return get_unexpected(); 809 | } 810 | \end{lstlisting} 811 | 812 | \end{frame} 813 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 814 | \begin{frame}[fragile] 815 | \frametitle{\cpp{mbind} member} 816 | 817 | \begin{lstlisting} 818 | template 819 | constexpr expected> 820 | expected::mbind(F&& f, 821 | REQUIRES( ! is_void_v> ) 822 | ) const 823 | { 824 | typedef expected> result_type; 825 | if (*this) return f(**this); 826 | else return get_unexpected(); 827 | } 828 | \end{lstlisting} 829 | 830 | \end{frame} 831 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 832 | \begin{frame}[fragile] 833 | \frametitle{\cpp{catch_error} member} 834 | 835 | \begin{lstlisting} 836 | template 837 | constexpr expected 838 | expected::catch_error(F&& f, 839 | REQUIRES( is_same_v, expected> ) 840 | ) const 841 | { 842 | if ( ! *this ) return f(error()); 843 | else return *this; 844 | } 845 | \end{lstlisting} 846 | 847 | \end{frame} 848 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 849 | \begin{frame}[fragile] 850 | \frametitle{\cpp{then}} 851 | 852 | \begin{lstlisting} 853 | template 854 | constexpr result_of_t 855 | expected::then(F&& f, 856 | REQUIRES( is_expected_v)> > ) 857 | ) 858 | { 859 | f(move(*this)); 860 | } 861 | \end{lstlisting} 862 | 863 | \end{frame} 864 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 865 | \subsection{Operators} 866 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 867 | \begin{frame}[fragile] 868 | \frametitle{Relational operators} 869 | 870 | \begin{itemize} 871 | \item unexpected values are always less than expected ones. 872 | \item How unexpected values compare? 873 | \item \cpp{std::exception_ptr} doesn't compare. 874 | \item Do we want \cpp{expected} be comparable? 875 | \item compare as \cpp{optional}? 876 | \item If yes, all the \cpp{unexpected_type} compare equals. 877 | \item This seems counterintuitive, as the observable behavior is different. 878 | 879 | \item \cpp{expected} is comparable if \cpp{unexpected_type} and \cpp{T} are comparable. 880 | \item \cpp{unexpected_type} is comparable if \cpp{E} is comparable and 881 | \item \cpp{unexpected_type} is not comparable. 882 | \end{itemize} 883 | 884 | \end{frame} 885 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 886 | \begin{frame}[fragile] 887 | \frametitle{Relational operators} 888 | 889 | \begin{lstlisting} 890 | template 891 | constexpr bool 892 | operator<(const expected& x, const expected& y) 893 | { 894 | return (x) 895 | ? (y) ? *x < *y : false 896 | : (y) ? true : x.get_unexpected() 900 | constexpr bool 901 | operator==(const expected& x, const expected& y) 902 | { 903 | return (x) 904 | ? (y) ? *x == *y : false 905 | : (y) ? false : x.get_unexpected()==y.get_unexpected(); 906 | } 907 | \end{lstlisting} 908 | 909 | \end{frame} 910 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 911 | \subsection{Factories} 912 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 913 | \begin{frame}[fragile] 914 | \frametitle{expected factories} 915 | 916 | \begin{lstlisting} 917 | template 918 | constexpr expected > 919 | make_expected(T&& v ) ; 920 | expected make_expected(); 921 | template 922 | expected 923 | make_expected_from_exception(E e) 924 | template 925 | constexpr expected, T> 926 | make_expected_from_error(E e); 927 | \end{lstlisting} 928 | 929 | \begin{lstlisting} 930 | auto e1 = make_expected(2); // expected 931 | auto e2 = make_expected_from_exception(bad_alloc()); 932 | // expected 933 | auto e3 = make_expected_from_error(errc::invalid); 934 | // expected 935 | \end{lstlisting} 936 | \end{frame} 937 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 938 | \begin{frame}[fragile] 939 | \frametitle{expected as a type constructor} 940 | 941 | \begin{lstlisting} 942 | auto e1 = make_expected(2); // compile fails 943 | auto e1 = expected(2); // int is redondant 944 | auto e2 = expected::make(2); // no redondant 945 | \end{lstlisting} 946 | 947 | \begin{lstlisting} 948 | template 949 | class expected; 950 | template 951 | class expected { 952 | public: 953 | template using type = expected; 954 | template expected make(T&& v) { 955 | return expected(std::forward(v)); 956 | } 957 | }; 958 | \end{lstlisting} 959 | \end{frame} 960 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 961 | \begin{frame}[fragile] 962 | \frametitle{Differences between \cpp{expected} and \cpp{expected}} 963 | 964 | \begin{tabular}{|c|c|c|} 965 | \hline 966 | & \cpp{expected} & \cpp{expected} \\ 967 | \hline 968 | \textbf{never-empty warranty} & if \cpp{E} & almost yes \\ 969 | \hline 970 | \textbf{relational operators} & if \cpp{E} and \cpp{T} & no \\ 971 | \hline 972 | \textbf{hash} & if \cpp{E} and \cpp{T} & no \\ 973 | \hline 974 | \textbf{has\_exception} & no & yes \\ 975 | \hline 976 | \textbf{catch\_exception} & no & yes \\ 977 | \hline 978 | \end{tabular} 979 | 980 | \begin{itemize} 981 | \item Should \cpp{expected} and \cpp{expected} be represented by two different classes? 982 | \end{itemize} 983 | 984 | \end{frame} 985 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 986 | \subsection{Related types} 987 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 988 | \begin{frame}[fragile] 989 | \frametitle{\cpp{boost::variant,T>} Comparison} 990 | 991 | \begin{tabular}{|c|c|c|} 992 | \hline 993 | & \textbf{variant} & \textbf{expected} \\ 994 | \hline 995 | \textbf{never-empty warranty} & yes & almost yes \\ 996 | \hline 997 | \textbf{factories} & no & yes \\ 998 | \hline 999 | \textbf{value\_type} & no & yes \\ 1000 | \hline 1001 | \textbf{default constructor} & yes (if E is ) & yes (if E is ) \\ 1002 | \hline 1003 | \textbf{observers} & get/get & operator*/value/error \\ 1004 | \hline 1005 | \textbf{visitation} & apply\_visitor & fmap/mbind/catch\_error \\ 1006 | \hline 1007 | \end{tabular} 1008 | \end{frame} 1009 | 1010 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1011 | \begin{frame}[fragile] 1012 | \frametitle{\cpp{std::future} and \cpp{expected} Comparison} 1013 | 1014 | \begin{tabular}{|c|c|c|} 1015 | \hline 1016 | & \textbf{future} & \textbf{expected} \\ 1017 | \hline 1018 | \textbf{specific null value} & no & no \\ 1019 | \hline 1020 | \textbf{relational operators} & no & depends \\ 1021 | \hline 1022 | \textbf{factories} & \cpp{make_ready_future} & \cpp{make_expected} \\ 1023 | \hline 1024 | \textbf{factories} & no & \cpp{make_unexpected} \\ 1025 | \hline 1026 | \textbf{emplace} & no & yes \\ 1027 | \hline 1028 | \textbf{value\_type} & no & yes \\ 1029 | \hline 1030 | \textbf{default constructor} & yes(invalid) & yes (\cpp{E()} ) \\ 1031 | \hline 1032 | \textbf{state} & \cpp{valid} / \cpp{ready} & \cpp{operator bool} \\ 1033 | \hline 1034 | \textbf{observers} & \cpp{get} /\cpp{ wait} & \cpp{operator*}/\cpp{value}/\cpp{error} \\ 1035 | \hline 1036 | \textbf{visitation} & \cpp{then} & \cpp{fmap}/\cpp{mbind}/\cpp{catch_error} \\ 1037 | \hline 1038 | \textbf{grouping} & \cpp{when_all}/\cpp{when_any} & n.a. \\ 1039 | \hline 1040 | \end{tabular} 1041 | \end{frame} 1042 | 1043 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1044 | \begin{frame}[fragile] 1045 | \frametitle{expected/future differences} 1046 | 1047 | \begin{itemize} 1048 | \item Should we add a \cpp{make>} as \cpp{make>}? 1049 | \item Should we make \cpp{future} be implicitly constructible from \cpp{unexpected_type>}? 1050 | \item Should we add emplace functions for \cpp{future}? 1051 | \item Should we add nested \cpp{value_type} to \cpp{future}? 1052 | \item Should we add \cpp{valid()} and \cpp{ready()} functions to \cpp{expected} that return always true? 1053 | \item Should we add \cpp{operator bool} to \cpp{future}? 1054 | \item Should we add \cpp{fmap()}/\cpp{mbind()}/\cpp{catch_error()} functions to \cpp{future}? 1055 | \item Should we add \cpp{value()} to \cpp{future}? 1056 | \item Should we add \cpp{error()} to \cpp{future}? 1057 | \end{itemize} 1058 | 1059 | \end{frame} 1060 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1061 | \begin{frame}[fragile] 1062 | \frametitle{Conversions from/to ready std::experimental::future } 1063 | 1064 | \begin{lstlisting} 1065 | template 1066 | expected make_expected(future&& f) { 1067 | assert (f.ready() && "future not ready"); 1068 | try { 1069 | return f.get(); 1070 | } catch (...) { 1071 | return make_unexpected_from_exception(); 1072 | } 1073 | } 1074 | \end{lstlisting} 1075 | 1076 | \begin{lstlisting} 1077 | template 1078 | std::future 1079 | make_ready_future(expected&& e) { 1080 | if (e) return make_ready_future(*e); 1081 | else return make_unexpected_future(e.error()); 1082 | } 1083 | \end{lstlisting} 1084 | \end{frame} 1085 | 1086 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1087 | \begin{frame}[fragile] 1088 | \frametitle{\cpp{make_unexpected_future} } 1089 | 1090 | \begin{lstlisting} 1091 | template 1092 | std::future make_unexpected_future(E e) { 1093 | std::promise p; 1094 | std::future f = p.get_future(); 1095 | p.set_exception(std::make_exception_ptr(e)); 1096 | return std::move(f); 1097 | } 1098 | \end{lstlisting} 1099 | 1100 | \end{frame} 1101 | 1102 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1103 | \begin{frame}[fragile] 1104 | \frametitle{\cpp{make_expected} alternative implementation } 1105 | 1106 | \begin{itemize} 1107 | \item If \cpp{future} stores the exception on a \cpp{exception_ptr}, could define this function as a friend function. 1108 | \end{itemize} 1109 | 1110 | \begin{lstlisting} 1111 | template 1112 | expected make_expected(future&& f) { 1113 | assert (f.ready() && "future not ready"); 1114 | lock_guard lk(f.get_mutex()); 1115 | if (f.has_value(lk)) return f.get(lk); 1116 | else return make_unexpected(f.get_exception_ptr(lk)); 1117 | } 1118 | \end{lstlisting} 1119 | 1120 | \begin{itemize} 1121 | \item If \cpp{future} stores a \cpp{expected}. 1122 | \end{itemize} 1123 | 1124 | \begin{lstlisting} 1125 | template 1126 | expected make_expected(future&& f) { 1127 | return expected(f); 1128 | } 1129 | \end{lstlisting} 1130 | 1131 | \end{frame} 1132 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1133 | \begin{frame}[fragile] 1134 | \frametitle{std::experimental::optional Comparison} 1135 | 1136 | \begin{itemize} 1137 | \item \cpp{expected} is as an \cpp{std::experimental::optional} that collapse all the values of \cpp{E} to \cpp{nullopt}. 1138 | \item \cpp{expected} should behave as much as possible as \cpp{optional}. 1139 | \end{itemize} 1140 | 1141 | \begin{tabular}{|c|c|c|} 1142 | \hline 1143 | & \textbf{optional} & \textbf{expected} \\ 1144 | \hline 1145 | \textbf{specific null value} & yes & no \\ 1146 | \hline 1147 | \textbf{relational operators} & yes & depends \\ 1148 | \hline 1149 | \textbf{swap} & yes & yes \\ 1150 | \hline 1151 | \textbf{factories} & \cpp{make_optional} & \cpp{make_expected} \\ 1152 | \hline 1153 | \textbf{value\_type} & no & yes \\ 1154 | \hline 1155 | \textbf{default constructor} & yes(\cpp{nullopt}) & yes (\cpp{E()} ) \\ 1156 | \hline 1157 | \textbf{observers} & \cpp{value} & \cpp{value} / \cpp{error} \\ 1158 | \hline 1159 | \textbf{unwrap} & no & yes \\ 1160 | \hline 1161 | \textbf{visitation} & no & \cpp{fmap}/\cpp{mbind}/\cpp{catch_error} \\ 1162 | \hline 1163 | \end{tabular} 1164 | \end{frame} 1165 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1166 | \begin{frame}[fragile] 1167 | \frametitle{expected/optional Differences } 1168 | 1169 | \begin{itemize} 1170 | \item Should we add a \cpp{make>} as \cpp{make>}? 1171 | \item Should we make \cpp{expected} be implicitly constructible from \cpp{E>}? 1172 | \item Should we add nested \cpp{value_type} to \cpp{optional}? 1173 | \item Should we add \cpp{fmap()}/\cpp{mbind()}/\cpp{catch_error()} functions to \cpp{optional}? 1174 | \item Should we add \cpp{error()} to \cpp{optional}? 1175 | \item Should we add \cpp{unwrap()} to \cpp{optional}? 1176 | \end{itemize} 1177 | 1178 | \end{frame} 1179 | 1180 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1181 | \begin{frame}[fragile] 1182 | \frametitle{std::experimental::optional Conversions} 1183 | 1184 | \begin{lstlisting} 1185 | template 1186 | optional make_optional(expected v) { 1187 | if (v) return make_optional(*v); 1188 | else nullopt; 1189 | } 1190 | \end{lstlisting} 1191 | 1192 | \begin{lstlisting} 1193 | struct conversion_from_nullopt {}; 1194 | template 1195 | expected make_expected(optional v) { 1196 | if (v) return make_expected(*v); 1197 | else make_unexpected(conversion_from_nullopt()); 1198 | } 1199 | \end{lstlisting} 1200 | \end{frame} 1201 | 1202 | \section{Open Points, Future Work and Conclusions} 1203 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1204 | \begin{frame} 1205 | \frametitle{Open Points ...} 1206 | 1207 | \begin{itemize} 1208 | \item Should the \cpp{operator==} collapse all the unexpected values? 1209 | \item Should \cpp{expected} and \cpp{expected} be represented by two different classes? 1210 | \item Should \cpp{expected} throw \cpp{E} instead of \cpp{bad_expected_access}? 1211 | \item Should \cpp{expected} be convertible from \cpp{E} when it is not convertible to \cpp{T}? 1212 | \item Should \cpp{fmap()}/\cpp{mbind()}/\cpp{catch_error()} expect that the continuation doesn't throws? 1213 | \item Should we have operators for \cpp{fmap()}/\cpp{mbind()}/\cpp{catch_error()} (\cpp{^}/\cpp{&}/\cpp{|})? 1214 | 1215 | \end{itemize} 1216 | 1217 | \end{frame} 1218 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1219 | \begin{frame}[fragile] 1220 | \frametitle{Infix operators} 1221 | 1222 | \begin{lstlisting} 1223 | auto e2 = e1 ^ f1 ^ f2; 1224 | \end{lstlisting} 1225 | 1226 | \begin{lstlisting} 1227 | auto e2 = e1 ^fmap^ f1 ^fmap^ f2; 1228 | \end{lstlisting} 1229 | 1230 | \begin{lstlisting} 1231 | return ( e1 <- f1 : e2 <- f2 : e1+e2 ) | rec; 1232 | \end{lstlisting} 1233 | 1234 | \begin{lstlisting} 1235 | return ( e1 <- f1 : e2 <- f2 : e1+e2 ) ^catch_error^ rec; 1236 | \end{lstlisting} 1237 | 1238 | 1239 | \end{frame} 1240 | 1241 | 1242 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1243 | \begin{frame} 1244 | \frametitle{Future Work ...} 1245 | 1246 | \begin{itemize} 1247 | \item Allocator support for expected. 1248 | \item Define a common visitation interface for \cpp{any}, \cpp{variant}, \cpp{exception_ptr}. 1249 | \item Define an Error concept that would make \cpp{expected} more generic. 1250 | \end{itemize} 1251 | 1252 | \end{frame} 1253 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1254 | \begin{frame} 1255 | \frametitle{Conclusions} 1256 | 1257 | \begin{itemize} 1258 | \item \cpp{expected} monadic functions are useful tools, 1259 | \item that allows to combine functions that return \cpp{expected} but, 1260 | \item it would be much easier to use it with a specific language do-expression. 1261 | \end{itemize} 1262 | 1263 | \begin{itemize} 1264 | \item \cpp{expected}, \cpp{future} and \cpp{optional} share a lot of things but have some differences. 1265 | \item Defining a common interface for the functions that have the same behavior allows us to define generic algorithms on top of these concepts. 1266 | \item Having a monadic common interface would be one step towards this goal. 1267 | \end{itemize} 1268 | 1269 | \end{frame} 1270 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 1271 | \begin{frame} 1272 | \begin{center} 1273 | \Large{Thanks for your attention!} 1274 | \end{center} 1275 | \begin{center} 1276 | \Large{Questions?} 1277 | \end{center} 1278 | \end{frame} 1279 | 1280 | 1281 | 1282 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1283 | 1284 | 1285 | \end{document} 1286 | -------------------------------------------------------------------------------- /cxxnow2014_expected_monads.tex: -------------------------------------------------------------------------------- 1 | \documentclass[xcolor=dvipsnames]{beamer} 2 | 3 | \usepackage[utf8]{inputenc} 4 | \usepackage[english]{babel} 5 | \usepackage{url} 6 | \usepackage{lmodern} 7 | \usepackage{listings} 8 | \usepackage{graphicx} 9 | \usepackage{xcolor} 10 | \usepackage{textcomp} 11 | \usepackage{hyperref} 12 | \usepackage{subcaption} 13 | \usepackage[T1]{fontenc} 14 | 15 | \usepackage{color} 16 | 17 | \definecolor{dkgreen}{rgb}{0,0.6,0} 18 | \definecolor{gray}{rgb}{0.5,0.5,0.5} 19 | \definecolor{mauve}{rgb}{0.58,0,0.82} 20 | 21 | \lstset{ 22 | language=c++, % the language of the code 23 | basicstyle=\footnotesize, % the size of the fonts that are used for the code 24 | numbers=left, % where to put the line-numbers 25 | numberstyle=\tiny\color{gray}, % the style that is used for the line-numbers 26 | stepnumber=1, % the step between two line-numbers. If it's 1, each line 27 | % will be numbered 28 | numbersep=5pt, % how far the line-numbers are from the code 29 | backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color} 30 | showtabs=false, % show tabs within strings adding particular underscores 31 | frame=single, % adds a frame around the code 32 | rulecolor=\color{black}, % if not set, the frame-color may be changed on line-breaks within not-black text (e.g. comments (green here)) 33 | tabsize=2, % sets default tabsize to 2 spaces 34 | captionpos=b, % sets the caption-position to bottom 35 | breaklines=true, % sets automatic line breaking 36 | breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace 37 | title=\lstname, % show the filename of files included with \lstinputlisting; 38 | % also try caption instead of title 39 | keywordstyle=\color{blue}, % keyword style 40 | commentstyle=\color{dkgreen}, % comment style 41 | stringstyle=\color{mauve}, % string literal style 42 | morekeywords={expect, await, constexpr, explicit} 43 | } 44 | 45 | \newcommand{\cpp}[1]{\lstinline{#1}} 46 | 47 | \setbeamertemplate{footline}{\hspace*{.5cm}\scriptsize{\insertauthor\hspace*{50pt} \hfill\insertframenumber\hspace*{.5cm}}} 48 | 49 | \setbeamertemplate{section in toc}{% 50 | \textcolor{MidnightBlue}{$\blacktriangleright$ \inserttocsection} 51 | } 52 | 53 | \usecolortheme{seahorse} 54 | \usecolortheme{rose} 55 | \useoutertheme{infolines} 56 | 57 | \usecolortheme[named=SkyBlue]{structure} 58 | \setbeamercolor{block title}{fg=MidnightBlue} 59 | 60 | \AtBeginSection[] 61 | { 62 | \begin{frame}{Content} 63 | \tableofcontents[currentsection,hideothersubsections] 64 | \end{frame} 65 | } 66 | 67 | \title{\textsc{Monads}: Alternative designs } 68 | \subtitle{C++Now 2014} 69 | \author[\textsc{Vicente Botet}]{Vicente \textsc{Botet Escriba}\texttt{vicente.botet@wanadoo.fr}} 70 | \institute[Alcatel-Lucent]{Alcatel-Lucent International-Lannion} 71 | \date[]{2014, May 16} 72 | 73 | \begin{document} 74 | \maketitle 75 | 76 | \section{Introduction} 77 | %%%%%%%%%% 78 | 79 | \subsection{About me} 80 | %%%%%%%%%%% 81 | 82 | \begin{frame} 83 | \frametitle{About Vicente Botet Escriba} 84 | 85 | % \begin{figure}[p] 86 | % \centering 87 | % \begin{subfigure}[b]{0.3\textwidth} 88 | % \includegraphics[scale=0.3]{images/vicente_botet.png} 89 | % \end{subfigure} 90 | % \qquad \qquad \quad 91 | % \begin{subfigure}[b]{0.3\textwidth} 92 | % \includegraphics[scale=0.3]{images/alu.jpg} 93 | % \end{subfigure} 94 | % \end{figure} 95 | 96 | \begin{itemize} 97 | \item Spanish. 98 | \item Work for Alcatel-Lucent International in Lannion - France. 99 | \item Interest in software engineering, language design, concurrency and STM. 100 | \end{itemize} 101 | 102 | \begin{block}{Open-source involvement} 103 | \begin{itemize} 104 | \item \textbf{Boost C++ library} Co-author and maintainer of Boost.Ratio, Boost.Chrono, Boost.Thread and some utilities in Boost.Utility. 105 | \item \textbf{Toward Boost C++ library} author of a lot of unfinished prototypes. 106 | \end{itemize} 107 | \end{block} 108 | \end{frame} 109 | 110 | \subsection{About Boost.Monads} 111 | %%%%%%%%%%%% 112 | \begin{frame} 113 | \frametitle{About Boost.Monads} 114 | 115 | \begin{itemize} 116 | \item After seen that \cpp{expected}, \cpp{optional} and \cpp{future} all could share the same Monad interface. 117 | \item we are looking for this common interface. 118 | \end{itemize} 119 | 120 | \begin{itemize} 121 | \item Git repository : https://github.com/ptal/Boost.Expected 122 | \end{itemize} 123 | \end{frame} 124 | 125 | \begin{frame}[fragile] 126 | \frametitle{Motivation} 127 | 128 | Problem: 129 | 130 | \begin{itemize} 131 | \item We want to define some algorithms that work for \cpp{expected}, \cpp{optional} and \cpp{future} between others. 132 | \item While these share a common underlying semantic, the interfaces are different. 133 | \item We need to define a common interface. 134 | \end{itemize} 135 | 136 | \end{frame} 137 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 138 | \section{Concepts design} 139 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 140 | \begin{frame}[fragile] 141 | \frametitle{Model to Concept Mapping} 142 | 143 | Should the mapping be automatic, that is, have a default mapping that is applied implicitly if the type conforms to some syntactical requirements? 144 | 145 | \begin{itemize} 146 | \item As concepts are more than syntax the explicit mapping seems mandatory. 147 | \item However this will be cumbersome, and the C++ standard library is based on syntax requirements. 148 | \end{itemize} 149 | 150 | Could several types share the same mapping? 151 | 152 | \begin{itemize} 153 | \item Several types could already be a model of another Concept that can be used to implement the mapping. 154 | \end{itemize} 155 | 156 | Could several mappings be applied to the same type? 157 | 158 | \begin{itemize} 159 | \item A type can be seen in several ways as a model of given concept. 160 | \end{itemize} 161 | 162 | 163 | \end{frame} 164 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 165 | \begin{frame}[fragile] 166 | \frametitle{Alternative designs} 167 | 168 | \begin{itemize} 169 | \item Direct: the model must provide the specific operations to conform to the Concept, E.g. the expression \cpp{*e} is well formed. 170 | \item Indirect: The concept is defined in terms of non-member functions. The developer of the model defines these non member functions for the specific model. E.g. the Concept requires that expression \cpp{deref(e)} is well formed and the Model mapping states how this operation is implemented using the Model. 171 | \item Mapper: All the features are mapped from the concept interface to the model interface. 172 | \end{itemize} 173 | \end{frame} 174 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 175 | \begin{frame}[fragile] 176 | \frametitle{Advantages/Liabilities} 177 | 178 | \begin{itemize} 179 | \item The direct alternative would need to change the interface of the Model to conform to the Concept, or to add a thin wrapper that adapts the interface and force the user to use the adaptor. 180 | \item The indirect and mapper alternatives are more open but both introduce non-member functions. 181 | \item The indirect approach could incur on violations of the ODR. 182 | \item In the mapper approach all the functions would need a mapper as template parameter as if the function is executed under this mapper. 183 | \item Only the mapper approach allows to have multiple mappings of a model to a concept. 184 | 185 | \end{itemize} 186 | 187 | \end{frame} 188 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 189 | \begin{frame}[fragile] 190 | \frametitle{Concept usage comparison} 191 | 192 | \begin{lstlisting} 193 | template < class PV> // Direct 194 | constexpr bool equal( const PV& x, const PV& y ) 195 | { 196 | return bool(x) != bool(y) ? false 197 | : ( bool(x) ? *x == *y : true ); 198 | } 199 | template // Indirect 200 | constexpr bool equal( const PV& x, const PV& y ) 201 | { 202 | return has_value(x) != has_value(y) ? false 203 | : ( has_value(x) ? deref(x) == deref(y) : true ); 204 | } 205 | template // Mapper 206 | constexpr bool equal( const PV& x, const PV& y ) 207 | { 208 | return has_value(x) != has_value(y) ? false 209 | : ( has_value(x) ? deref(x) == deref(y) : true ); 210 | } 211 | \end{lstlisting} 212 | 213 | \end{frame} 214 | 215 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 216 | \section{Monadic Concepts} 217 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 218 | \subsection{Rebindable} 219 | %%%%%%%%%%%% 220 | 221 | \begin{frame}[fragile] 222 | \frametitle{Rebindable features} 223 | 224 | Rebindable is a basic concept that provides a way to 225 | 226 | \begin{itemize} 227 | \item \cpp{value_type} : obtain the type of the underlying value, 228 | \item \cpp{type_constructor} : obtain the type constructor. 229 | \item \cpp{rebind} : build another type substituting the underlying value type. 230 | \end{itemize} 231 | 232 | satisfying 233 | 234 | \begin{lstlisting} 235 | is_same, value_type>, M>::value 236 | is_same>, TC>::value 237 | is_same>, M>::value 238 | is_same, apply,U>>::value 239 | \end{lstlisting} 240 | 241 | \end{frame} 242 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 243 | \begin{frame}[fragile] 244 | \frametitle{Rebindable features} 245 | 246 | Where 247 | 248 | \begin{lstlisting} 249 | template 250 | using apply = typename F::template type; 251 | \end{lstlisting} 252 | 253 | Examples: 254 | \begin{itemize} 255 | \item pointers: \cpp{T*}, 256 | \item smart pointers: \cpp{shared_ptr}, 257 | \item containers, \cpp{vector}, \cpp{array}, \cpp{T[N]} 258 | \item wrappers: \cpp{optional}, \cpp{expected}, \cpp{future}, 259 | \item other: \cpp{allocator} 260 | \end{itemize} 261 | 262 | \end{frame} 263 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 264 | \subsection{PossiblyValued} 265 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 266 | \begin{frame}[fragile] 267 | \frametitle{PossiblyValued features} 268 | 269 | PossiblyValued is a refinement of a Rebindable concept that allows to 270 | 271 | \begin{itemize} 272 | \item \cpp{has_value(m)}: check if a value is present. 273 | \item \cpp{deref(m)}: obtain a reference to the value. (defined only if \cpp{has_value}). 274 | \item \cpp{value(m)}: get a reference to the stored value or throw an exception. 275 | 276 | \item \cpp{error_type}: obtain the associated error type. 277 | \item \cpp{error(m)}: get a reference to the stored error (defined only if \cpp{has_value} is false). 278 | 279 | \item \cpp{errored_type}: obtain the associated errored type, which is implicitly convertible to the model. 280 | \item \cpp{make_errored(m)}: get a value storing the stored error that is convertible to the model. 281 | 282 | \end{itemize} 283 | \end{frame} 284 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 285 | \begin{frame}[fragile] 286 | \frametitle{PossiblyValued algorithms} 287 | 288 | \begin{lstlisting} 289 | template 290 | // requires PossiblyValued 291 | // && EqualityComparable> 292 | constexpr bool equal( const PV& x, const PV& y ) { 293 | return has_value(x) != has_value(y) ? false 294 | : ( has_value(x) ? deref(x) == deref(y) : true ); 295 | } 296 | \end{lstlisting} 297 | 298 | \begin{lstlisting} 299 | template 300 | // requires PossiblyValued 301 | // && Convertible,U> 302 | constexpr value_type value_or( const PV& x, U&& y ) { 303 | return has_value(x) ? deref(x) : value_type(y); 304 | } 305 | \end{lstlisting} 306 | 307 | \end{frame} 308 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 309 | \subsection{Functor} 310 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 311 | \begin{frame}[fragile] 312 | \frametitle{C++ 'Functor'} 313 | 314 | \cpp{Functor} is a refinement of Rebindable for type wrappers that can be mapped over. It provides a 315 | 316 | \begin{itemize} 317 | \item \cpp{fmap(f,m)}: traverse a functor applying a function. 318 | \end{itemize} 319 | 320 | satisfying 321 | 322 | \begin{lstlisting} 323 | bind(fmap,id,_1) == bind(id,_1) 324 | bind(fmap, compose(f, g), _1) == 325 | compose(bind(fmap, f,_1), bind(fmap, g, _1) 326 | \end{lstlisting} 327 | 328 | \end{frame} 329 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 330 | \begin{frame}[fragile] 331 | \frametitle{\cpp{Functor}: Overloads of \cpp{fmap}} 332 | 333 | \begin{lstlisting} 334 | template 335 | auto fmap(F&& f, M&& m) 336 | -> decltype( m.fmap(forward(f)) ) { 337 | return m.fmap(forward(f)); 338 | } 339 | // overload for optional 340 | template 341 | auto fmap(F&& f, optional&& m) 342 | -> decltype(make_optional(f(*m))) { 343 | if (m) return make_optional(f(*m)); 344 | else return nullopt; 345 | } 346 | \end{lstlisting} 347 | 348 | \begin{lstlisting} 349 | optional f1; 350 | auto f2 = fmap(fct, f1); 351 | \end{lstlisting} 352 | 353 | \end{frame} 354 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 355 | \begin{frame}[fragile] 356 | \frametitle{\cpp{Functor}: Chain syntax for \cpp{fmap}} 357 | 358 | \begin{lstlisting} 359 | // very nice chain syntax. 360 | auto f2 = f1.fmap(fct1).fmap(fct2); 361 | 362 | // ugly functional syntax 363 | auto f2 = fmap(fct2, fmap(fct1, f1)); 364 | 365 | // nice chain syntax. 366 | optional f2 = as_functor(f1).fmap(fct1).fmap(fct2); 367 | auto f2 = as_functor(f1).fmap(fct1).fmap(fct2).get(); 368 | 369 | // nice operator syntax. 370 | optional f2 = as_functor(f1) >> fct1 >> fct2; 371 | \end{lstlisting} 372 | 373 | \end{frame} 374 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 375 | \begin{frame}[fragile] 376 | \frametitle{C++ Functor - Specialization for PossiblyValued} 377 | 378 | Specialization for models of \cpp{PossiblyValued} 379 | 380 | \begin{lstlisting} 381 | template 382 | // requires PossiblyValued 383 | // && Invokable> 384 | rebind)> fmap(F&& f, M&& m) { 385 | return has_value( forward(m)) 386 | ? forward(f)( deref( forward(m) ) ) 387 | : make_errored(forward(m) ) ); 388 | } 389 | \end{lstlisting} 390 | 391 | \end{frame} 392 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 393 | \subsection{Monad} 394 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 395 | \begin{frame}[fragile] 396 | \frametitle{Monad} 397 | 398 | \cpp{Monad} is a refinement of \cpp{Functor} concept providing a way to: 399 | 400 | \begin{itemize} 401 | \item \cpp{make(v)}: build a monad instance from the underlying value type. 402 | \item \cpp{mbind(m, f)} : binds a function that will be called only if the action associated to the Monad succeeds. 403 | \item \cpp{mdo(m1, m2)} : sequentially compose two actions, discarding any value produced by the first. 404 | \end{itemize} 405 | 406 | satisfying 407 | 408 | \begin{lstlisting} 409 | mbind(make(x), f) == f(x) 410 | mbind(m, [](auto x) { return make(x);} ) == m 411 | mbind(m, [](auto x) { return mbind(f(x), g); } == 412 | mbind(mbind(m, f), g) 413 | 414 | fmap(f, m) == 415 | mbind(m, compose([](auto x) { return make(x);}, f)) 416 | \end{lstlisting} 417 | \end{frame} 418 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 419 | \begin{frame}[fragile] 420 | \frametitle{Non-uniform type factories} 421 | 422 | \begin{lstlisting} 423 | auto e1 = make_expected(2); 424 | auto e2 = expected<>::make(2); 425 | auto e2 = expected::make(2); 426 | 427 | auto o = make_optional(2); 428 | auto f = make_ready_future(2); 429 | \end{lstlisting} 430 | 431 | \begin{itemize} 432 | \item Non-uniform syntax -> no generic algorithms 433 | \end{itemize} 434 | 435 | \end{frame} 436 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 437 | \begin{frame}[fragile] 438 | \frametitle{Uniform type factories - type constructor} 439 | 440 | \begin{itemize} 441 | \item Type constructor 442 | \end{itemize} 443 | 444 | \begin{lstlisting} 445 | auto e2 = make>(2); 446 | auto e2 = make>(2); 447 | auto o = make>(2); 448 | auto f = make>(2); 449 | \end{lstlisting} 450 | \end{frame} 451 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 452 | \begin{frame}[fragile] 453 | \frametitle{\cpp{expected} as a type constructor} 454 | 455 | \begin{lstlisting} 456 | auto e = make>(2); 457 | // e has type expected 458 | auto e = make>(2); 459 | // e has type expected 460 | \end{lstlisting} 461 | 462 | \begin{lstlisting} 463 | template 464 | constexpr apply> make(T&& v) 465 | { 466 | return apply>(std::forward(v)); 467 | } 468 | \end{lstlisting} 469 | 470 | \end{frame} 471 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% 472 | \begin{frame}[fragile] 473 | \frametitle{Uniform type factories - Lifting } 474 | 475 | \begin{itemize} 476 | \item Lifting variadic template class to create a type constructor 477 | \end{itemize} 478 | 479 | \begin{lstlisting} 480 | template