group__group-Monad.html 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. <!--
  2. Copyright Louis Dionne 2013-2017
  3. Distributed under the Boost Software License, Version 1.0.
  4. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  5. -->
  6. <!-- boost-no-inspect -->
  7. <!-- HTML header for doxygen 1.8.9.1-->
  8. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  9. <html xmlns="http://www.w3.org/1999/xhtml">
  10. <head>
  11. <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
  12. <meta http-equiv="X-UA-Compatible" content="IE=9"/>
  13. <meta name="generator" content="Doxygen 1.8.15"/>
  14. <title>Boost.Hana: Monad</title>
  15. <link href="tabs.css" rel="stylesheet" type="text/css"/>
  16. <script type="text/javascript" src="jquery.js"></script>
  17. <script type="text/javascript" src="dynsections.js"></script>
  18. <link href="navtree.css" rel="stylesheet" type="text/css"/>
  19. <script type="text/javascript" src="resize.js"></script>
  20. <script type="text/javascript" src="navtreedata.js"></script>
  21. <script type="text/javascript" src="navtree.js"></script>
  22. <script type="text/javascript">
  23. /* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
  24. $(document).ready(initResizable);
  25. /* @license-end */</script>
  26. <link href="search/search.css" rel="stylesheet" type="text/css"/>
  27. <script type="text/javascript" src="search/searchdata.js"></script>
  28. <script type="text/javascript" src="search/search.js"></script>
  29. <script type="text/javascript">
  30. /* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
  31. $(document).ready(function() { init_search(); });
  32. /* @license-end */
  33. </script>
  34. <script type="text/x-mathjax-config">
  35. MathJax.Hub.Config({
  36. extensions: ["tex2jax.js"],
  37. jax: ["input/TeX","output/HTML-CSS"],
  38. });
  39. // Copyright Louis Dionne 2013-2017
  40. // Distributed under the Boost Software License, Version 1.0.
  41. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  42. MathJax.Hub.Config({
  43. "HTML-CSS": {
  44. linebreaks: {
  45. automatic: true,
  46. width: "75% container"
  47. }
  48. }
  49. });
  50. </script><script type="text/javascript" async="async" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js"></script>
  51. <link href="doxygen.css" rel="stylesheet" type="text/css" />
  52. <!-- Additional javascript for drawing charts. -->
  53. <script type="text/javascript" src="highcharts.js"></script>
  54. <script type="text/javascript" src="highcharts-data.js"></script>
  55. <script type="text/javascript" src="highcharts-exporting.js"></script>
  56. <script type="text/javascript" src="chart.js"></script>
  57. <script type="text/javascript" src="hana.js"></script>
  58. </head>
  59. <body>
  60. <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
  61. <div id="titlearea">
  62. <table cellspacing="0" cellpadding="0">
  63. <tbody>
  64. <tr style="height: 56px;">
  65. <td id="projectlogo"><img alt="Logo" src="Boost.png"/></td>
  66. <td style="padding-left: 0.5em;">
  67. <div id="projectname">Boost.Hana
  68. &#160;<span id="projectnumber">1.6.0</span>
  69. </div>
  70. <div id="projectbrief">Your standard library for metaprogramming</div>
  71. </td>
  72. <td> <div id="MSearchBox" class="MSearchBoxInactive">
  73. <span class="left">
  74. <img id="MSearchSelect" src="search/mag_sel.png"
  75. onmouseover="return searchBox.OnSearchSelectShow()"
  76. onmouseout="return searchBox.OnSearchSelectHide()"
  77. alt=""/>
  78. <input type="text" id="MSearchField" value="Search" accesskey="S"
  79. onfocus="searchBox.OnSearchFieldFocus(true)"
  80. onblur="searchBox.OnSearchFieldFocus(false)"
  81. onkeyup="searchBox.OnSearchFieldChange(event)"/>
  82. </span><span class="right">
  83. <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
  84. </span>
  85. </div>
  86. </td>
  87. </tr>
  88. </tbody>
  89. </table>
  90. </div>
  91. <!-- end header part -->
  92. <!-- Generated by Doxygen 1.8.15 -->
  93. <script type="text/javascript">
  94. /* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
  95. var searchBox = new SearchBox("searchBox", "search",false,'Search');
  96. /* @license-end */
  97. </script>
  98. </div><!-- top -->
  99. <div id="side-nav" class="ui-resizable side-nav-resizable">
  100. <div id="nav-tree">
  101. <div id="nav-tree-contents">
  102. <div id="nav-sync" class="sync"></div>
  103. </div>
  104. </div>
  105. <div id="splitbar" style="-moz-user-select:none;"
  106. class="ui-resizable-handle">
  107. </div>
  108. </div>
  109. <script type="text/javascript">
  110. /* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
  111. $(document).ready(function(){initNavTree('group__group-Monad.html','');});
  112. /* @license-end */
  113. </script>
  114. <div id="doc-content">
  115. <!-- window showing the filter options -->
  116. <div id="MSearchSelectWindow"
  117. onmouseover="return searchBox.OnSearchSelectShow()"
  118. onmouseout="return searchBox.OnSearchSelectHide()"
  119. onkeydown="return searchBox.OnSearchSelectKey(event)">
  120. </div>
  121. <!-- iframe showing the search results (closed by default) -->
  122. <div id="MSearchResultsWindow">
  123. <iframe src="javascript:void(0)" frameborder="0"
  124. name="MSearchResults" id="MSearchResults">
  125. </iframe>
  126. </div>
  127. <div class="header">
  128. <div class="summary">
  129. <a href="#var-members">Variables</a> </div>
  130. <div class="headertitle">
  131. <div class="title">Monad<div class="ingroups"><a class="el" href="group__group-concepts.html">Concepts</a></div></div> </div>
  132. </div><!--header-->
  133. <div class="contents">
  134. <a name="details" id="details"></a><h2 class="groupheader">Description</h2>
  135. <p>The <code>Monad</code> concept represents <code>Applicative</code>s with the ability to flatten nested levels of structure. </p>
  136. <p>Historically, Monads are a construction coming from category theory, an abstract branch of mathematics. The functional programming community eventually discovered how Monads could be used to formalize several useful things like side effects, which led to the wide adoption of Monads in that community. However, even in a multi-paradigm language like C++, there are several constructs which turn out to be Monads, like <code>std::optional</code>, <code>std::vector</code> and others.</p>
  137. <p>Everybody tries to introduce <code>Monad</code>s with a different analogy, and most people fail. This is called the <a href="https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/">Monad tutorial fallacy</a>. We will try to avoid this trap by not presenting a specific intuition, and we will instead present what monads are mathematically. For specific intuitions, we will let readers who are new to this concept read one of the many excellent tutorials available online. Understanding Monads might take time at first, but once you get it, a lot of patterns will become obvious Monads; this enlightening will be your reward for the hard work.</p>
  138. <p>There are different ways of defining a Monad; Haskell uses a function called <code>bind</code> (<code>&gt;&gt;=</code>) and another one called <code>return</code> (it has nothing to do with C++'s <code>return</code> statement). They then introduce relationships that must be satisfied for a type to be a Monad with those functions. Mathematicians sometimes use a function called <code>join</code> and another one called <code>unit</code>, or they also sometimes use other category theoretic constructions like functor adjunctions and the Kleisli category.</p>
  139. <p>This library uses a composite approach. First, we use the <code>flatten</code> function (equivalent to <code>join</code>) along with the <code>lift</code> function from <code>Applicative</code> (equivalent to <code>unit</code>) to introduce the notion of monadic function composition. We then write the properties that must be satisfied by a Monad using this monadic composition operator, because we feel it shows the link between Monads and Monoids more clearly than other approaches.</p>
  140. <p>Roughly speaking, we will say that a <code>Monad</code> is an <code>Applicative</code> which also defines a way to compose functions returning a monadic result, as opposed to only being able to compose functions returning a normal result. We will then ask for this composition to be associative and to have a neutral element, just like normal function composition. For usual composition, the neutral element is the identity function <code>id</code>. For monadic composition, the neutral element is the <code>lift</code> function defined by <code>Applicative</code>. This construction is made clearer in the laws below.</p>
  141. <dl class="section note"><dt>Note</dt><dd>Monads are known to be a big chunk to swallow. However, it is out of the scope of this documentation to provide a full-blown explanation of the concept. The <a href="https://wiki.haskell.org/Typeclassopedia#Monad">Typeclassopedia</a> is a nice Haskell-oriented resource where more information about Monads can be found.</dd></dl>
  142. <h2>Minimal complete definitions </h2>
  143. <p>First, a <code>Monad</code> must be both a <code>Functor</code> and an <code>Applicative</code>. Also, an implementation of <code>flatten</code> or <code>chain</code> satisfying the laws below for monadic composition must be provided.</p>
  144. <dl class="section note"><dt>Note</dt><dd>The <code>ap</code> method for <code>Applicatives</code> may be derived from the minimal complete definition of <code>Monad</code> and <code>Functor</code>; see below for more information.</dd></dl>
  145. <h2>Laws </h2>
  146. <p>To simplify writing the laws, we use the comparison between functions. For two functions <code>f</code> and <code>g</code>, we define </p><div class="fragment"><div class="line">f == g <span class="keywordflow">if</span> and only <span class="keywordflow">if</span> f(x) == g(x) <span class="keywordflow">for</span> <a class="code" href="group__group-Searchable.html#ga81ae9764dd7818ad36270c6419fb1082">all</a> x</div></div><!-- fragment --><p>With the usual composition of functions, we are given two functions \( f : A \to B \) and \( g : B \to C \), and we must produce a new function \( compose(g, f) : A \to C \). This composition of functions is associative, which means that </p><div class="fragment"><div class="line"><a class="code" href="group__group-functional.html#ga3b16146e53efcdf9ecbb9a7b21f8cd0b">compose</a>(h, <a class="code" href="group__group-functional.html#ga3b16146e53efcdf9ecbb9a7b21f8cd0b">compose</a>(g, f)) == <a class="code" href="group__group-functional.html#ga3b16146e53efcdf9ecbb9a7b21f8cd0b">compose</a>(<a class="code" href="group__group-functional.html#ga3b16146e53efcdf9ecbb9a7b21f8cd0b">compose</a>(h, g), f)</div></div><!-- fragment --><p>Also, this composition has an identity element, which is the identity function. This simply means that </p><div class="fragment"><div class="line"><a class="code" href="group__group-functional.html#ga3b16146e53efcdf9ecbb9a7b21f8cd0b">compose</a>(f, <span class="keywordtype">id</span>) == <a class="code" href="group__group-functional.html#ga3b16146e53efcdf9ecbb9a7b21f8cd0b">compose</a>(<span class="keywordtype">id</span>, f) == f</div></div><!-- fragment --><p>This is probably nothing new if you are reading the <code>Monad</code> laws. Now, we can observe that the above is equivalent to saying that functions with the composition operator form a <code>Monoid</code>, where the neutral element is the identity function.</p>
  147. <p>Given an <code>Applicative</code> <code>F</code>, what if we wanted to compose two functions \( f : A \to F(B) \) and \( g : B \to F(C) \)? When the <code>Applicative</code> <code>F</code> is also a <code>Monad</code>, such functions taking normal values but returning monadic values are called <em>monadic functions</em>. To compose them, we obviously can't use normal function composition, since the domains and codomains of <code>f</code> and <code>g</code> do not match properly. Instead, we'll need a new operator &ndash; let's call it <code>monadic_compose</code>: </p><p class="formulaDsp">
  148. \[ \mathtt{monadic\_compose} : (B \to F(C)) \times (A \to F(B)) \to (A \to F(C)) \]
  149. </p>
  150. <p>How could we go about implementing this function? Well, since we know <code>F</code> is an <code>Applicative</code>, the only functions we have are <code>transform</code> (from <code>Functor</code>), and <code>lift</code> and <code>ap</code> (from <code>Applicative</code>). Hence, the only thing we can do at this point while respecting the signatures of <code>f</code> and <code>g</code> is to set (for <code>x</code> of type <code>A</code>) </p><div class="fragment"><div class="line"><a class="code" href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">monadic_compose</a>(g, f)(x) = <a class="code" href="group__group-Functor.html#ga5a8975f6e55375d5b6038a9c36ee63e7">transform</a>(f(x), g)</div></div><!-- fragment --><p>Indeed, <code>f(x)</code> is of type <code>F(B)</code>, so we can map <code>g</code> (which takes <code>B</code>'s) on it. Doing so will leave us with a result of type <code>F(F(C))</code>, but what we wanted was a result of type <code>F(C)</code> to respect the signature of <code>monadic_compose</code>. If we had a joker of type \( F(F(C)) \to F(C) \), we could simply set </p><div class="fragment"><div class="line"><a class="code" href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">monadic_compose</a>(g, f)(x) = joker(<a class="code" href="group__group-Functor.html#ga5a8975f6e55375d5b6038a9c36ee63e7">transform</a>(f(x), g))</div></div><!-- fragment --><p>and we would be happy. It turns out that <code>flatten</code> is precisely this joker. Now, we'll want our joker to satisfy some properties to make sure this composition is associative, just like our normal composition was. These properties are slightly cumbersome to specify, so we won't do it here. Also, we'll need some kind of neutral element for the composition. This neutral element can't be the usual identity function, because it does not have the right type: our neutral element needs to be a function of type \( X \to F(X) \) but the identity function has type \( X \to X \). It is now the right time to observe that <code>lift</code> from <code>Applicative</code> has exactly the right signature, and so we'll take this for our neutral element.</p>
  151. <p>We are now ready to formulate the <code>Monad</code> laws using this composition operator. For a <code>Monad</code> <code>M</code> and functions \( f : A \to M(B) \), \( g : B \to M(C) \) and \( h : C \to M(D) \), the following must be satisfied: </p><div class="fragment"><div class="line"><span class="comment">// associativity</span></div><div class="line"><a class="code" href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">monadic_compose</a>(h, <a class="code" href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">monadic_compose</a>(g, f)) == <a class="code" href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">monadic_compose</a>(<a class="code" href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">monadic_compose</a>(h, g), f)</div><div class="line"></div><div class="line"><span class="comment">// right identity</span></div><div class="line"><a class="code" href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">monadic_compose</a>(f, <a class="code" href="group__group-Applicative.html#ga712038d7abbc7159f8792788f7cd0c73">lift</a>&lt;M(A)&gt;) == f</div><div class="line"></div><div class="line"><span class="comment">// left identity</span></div><div class="line"><a class="code" href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">monadic_compose</a>(<a class="code" href="group__group-Applicative.html#ga712038d7abbc7159f8792788f7cd0c73">lift</a>&lt;M(B)&gt;, f) == f</div></div><!-- fragment --><p>which is to say that <code>M</code> along with monadic composition is a Monoid where the neutral element is <code>lift</code>.</p>
  152. <h2>Refined concepts </h2>
  153. <ol type="1">
  154. <li><code>Functor</code></li>
  155. <li><code>Applicative</code> (free implementation of <code>ap</code>)<br />
  156. When the minimal complete definition for <code>Monad</code> and <code>Functor</code> are both satisfied, it is possible to implement <code>ap</code> by setting <div class="fragment"><div class="line"><a class="code" href="group__group-Applicative.html#ga6176a32953dbbdee96e3ab3c73e4c890">ap</a>(fs, xs) = <a class="code" href="group__group-Monad.html#ga05fdc2f887cb9967357487a432ace98b">chain</a>(fs, [](<span class="keyword">auto</span> f) {</div><div class="line"> <span class="keywordflow">return</span> <a class="code" href="group__group-Functor.html#ga5a8975f6e55375d5b6038a9c36ee63e7">transform</a>(xs, f);</div><div class="line">})</div></div><!-- fragment --></li>
  157. </ol>
  158. <h2>Concrete models </h2>
  159. <p><code><a class="el" href="structboost_1_1hana_1_1lazy.html" title="hana::lazy implements superficial laziness via a monadic interface.">hana::lazy</a></code>, <code><a class="el" href="structboost_1_1hana_1_1optional.html" title="Optional value whose optional-ness is known at compile-time.">hana::optional</a></code>, <code><a class="el" href="structboost_1_1hana_1_1tuple.html" title="General purpose index-based heterogeneous sequence with a fixed length.">hana::tuple</a></code> </p>
  160. <table class="memberdecls">
  161. <tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="var-members"></a>
  162. Variables</h2></td></tr>
  163. <tr class="memitem:ga05fdc2f887cb9967357487a432ace98b"><td class="memItemLeft" align="right" valign="top">constexpr auto&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__group-Monad.html#ga05fdc2f887cb9967357487a432ace98b">boost::hana::chain</a></td></tr>
  164. <tr class="memdesc:ga05fdc2f887cb9967357487a432ace98b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Feed a monadic value into a monadic computation.Given a monadic value and a monadic function, <code>chain</code> feeds the monadic value into the function, thus performing some Monad-specific effects, and returns the result. An implementation of <code>chain</code> must satisfy. <a href="group__group-Monad.html#ga05fdc2f887cb9967357487a432ace98b">More...</a><br /></td></tr>
  165. <tr class="separator:ga05fdc2f887cb9967357487a432ace98b"><td class="memSeparator" colspan="2">&#160;</td></tr>
  166. <tr class="memitem:gaa5fec6fb418de5da3ecb500fd6cc54dd"><td class="memItemLeft" align="right" valign="top">constexpr auto&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__group-Monad.html#gaa5fec6fb418de5da3ecb500fd6cc54dd">boost::hana::flatten</a></td></tr>
  167. <tr class="memdesc:gaa5fec6fb418de5da3ecb500fd6cc54dd"><td class="mdescLeft">&#160;</td><td class="mdescRight">Collapse two levels of monadic structure into a single level.Given a monadic value wrapped into two levels of monad, <code>flatten</code> removes one such level. An implementation of <code>flatten</code> must satisfy. <a href="group__group-Monad.html#gaa5fec6fb418de5da3ecb500fd6cc54dd">More...</a><br /></td></tr>
  168. <tr class="separator:gaa5fec6fb418de5da3ecb500fd6cc54dd"><td class="memSeparator" colspan="2">&#160;</td></tr>
  169. <tr class="memitem:gaec3fe26c7378fd3057af83e03bd9b104"><td class="memItemLeft" align="right" valign="top">constexpr auto&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">boost::hana::monadic_compose</a></td></tr>
  170. <tr class="memdesc:gaec3fe26c7378fd3057af83e03bd9b104"><td class="mdescLeft">&#160;</td><td class="mdescRight">Composition of monadic functions.Given two monadic functions <code>f</code> and <code>g</code>, <code>monadic_compose</code> returns a new function equivalent to the composition of <code>f</code> with <code>g</code>, except the result of <code>g</code> is <code>chain</code>ed into <code>f</code> instead of simply passed to it, as with normal composition. <code>monadic_compose</code> satisfies. <a href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">More...</a><br /></td></tr>
  171. <tr class="separator:gaec3fe26c7378fd3057af83e03bd9b104"><td class="memSeparator" colspan="2">&#160;</td></tr>
  172. <tr class="memitem:ga5e0735de01a24f681c55aedfeb6d13bf"><td class="memTemplParams" colspan="2">template&lt;typename M &gt; </td></tr>
  173. <tr class="memitem:ga5e0735de01a24f681c55aedfeb6d13bf"><td class="memTemplItemLeft" align="right" valign="top">constexpr auto&#160;</td><td class="memTemplItemRight" valign="bottom"><a class="el" href="group__group-Monad.html#ga5e0735de01a24f681c55aedfeb6d13bf">boost::hana::tap</a></td></tr>
  174. <tr class="memdesc:ga5e0735de01a24f681c55aedfeb6d13bf"><td class="mdescLeft">&#160;</td><td class="mdescRight">Tap inside a monadic chain.Given a function <code>f</code>, <code>tap&lt;M&gt;</code> returns a new function which performs <code>f</code> on its argument and then returns the argument lifted in the <code>M</code> <code>Monad</code>. Combined with the property that <code>chain(m, lift&lt;M&gt;) == m</code>, this provides a way of executing an action inside a monadic chain without influencing its overall result. This is useful to e.g. insert debug statements or perform actions that are not tied to the chain but that need to be executed inside of it. <a href="group__group-Monad.html#ga5e0735de01a24f681c55aedfeb6d13bf">More...</a><br /></td></tr>
  175. <tr class="separator:ga5e0735de01a24f681c55aedfeb6d13bf"><td class="memSeparator" colspan="2">&#160;</td></tr>
  176. <tr class="memitem:gaaddd3789de43cf989babb10cdc0b447a"><td class="memItemLeft" align="right" valign="top">constexpr auto&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__group-Monad.html#gaaddd3789de43cf989babb10cdc0b447a">boost::hana::then</a></td></tr>
  177. <tr class="memdesc:gaaddd3789de43cf989babb10cdc0b447a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Sequentially compose two monadic actions, discarding any value produced by the first but not its effects. <a href="group__group-Monad.html#gaaddd3789de43cf989babb10cdc0b447a">More...</a><br /></td></tr>
  178. <tr class="separator:gaaddd3789de43cf989babb10cdc0b447a"><td class="memSeparator" colspan="2">&#160;</td></tr>
  179. </table>
  180. <h2 class="groupheader">Variable Documentation</h2>
  181. <a id="ga05fdc2f887cb9967357487a432ace98b"></a>
  182. <h2 class="memtitle"><span class="permalink"><a href="#ga05fdc2f887cb9967357487a432ace98b">&#9670;&nbsp;</a></span>chain</h2>
  183. <div class="memitem">
  184. <div class="memproto">
  185. <table class="memname">
  186. <tr>
  187. <td class="memname">constexpr auto boost::hana::chain</td>
  188. </tr>
  189. </table>
  190. </div><div class="memdoc">
  191. <p><code>#include &lt;<a class="el" href="fwd_2chain_8hpp.html">boost/hana/fwd/chain.hpp</a>&gt;</code></p>
  192. <b>Initial value:</b><div class="fragment"><div class="line">= [](<span class="keyword">auto</span>&amp;&amp; xs, <span class="keyword">auto</span>&amp;&amp; f) -&gt; decltype(<span class="keyword">auto</span>) {</div><div class="line"> <span class="keywordflow">return</span> tag-dispatched;</div><div class="line"> }</div></div><!-- fragment -->
  193. <p>Feed a monadic value into a monadic computation.Given a monadic value and a monadic function, <code>chain</code> feeds the monadic value into the function, thus performing some Monad-specific effects, and returns the result. An implementation of <code>chain</code> must satisfy. </p>
  194. <div class="fragment"><div class="line"><a class="code" href="group__group-Monad.html#ga05fdc2f887cb9967357487a432ace98b">chain</a>(xs, f) == <a class="code" href="group__group-Monad.html#gaa5fec6fb418de5da3ecb500fd6cc54dd">flatten</a>(<a class="code" href="group__group-Functor.html#ga5a8975f6e55375d5b6038a9c36ee63e7">transform</a>(xs, f))</div></div><!-- fragment --><h2>Signature </h2>
  195. <p>For a monad <code>M</code>, given a monadic value of type <code>M(A)</code> and a monadic function \( f : A \to M(B) \), <code>chain</code> has the signature \( \mathtt{chain} : M(A) \times (A \to M(B)) \to M(B) \).</p>
  196. <dl class="params"><dt>Parameters</dt><dd>
  197. <table class="params">
  198. <tr><td class="paramname">xs</td><td>A monadic value to be fed to the function <code>f</code>.</td></tr>
  199. <tr><td class="paramname">f</td><td>A function taking a normal value in the <code>xs</code> structure, and returning a monadic value. This function is called as <code>f(x)</code>, where <code>x</code> is an element of the structure <code>xs</code>.</td></tr>
  200. </table>
  201. </dd>
  202. </dl>
  203. <h2>Example </h2>
  204. <div class="fragment"><div class="line"><span class="comment">// Copyright Louis Dionne 2013-2017</span></div><div class="line"><span class="comment">// Distributed under the Boost Software License, Version 1.0.</span></div><div class="line"><span class="comment">// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="assert_8hpp.html">boost/hana/assert.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="chain_8hpp.html">boost/hana/chain.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="config_8hpp.html">boost/hana/config.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="equal_8hpp.html">boost/hana/equal.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="optional_8hpp.html">boost/hana/optional.hpp</a>&gt;</span></div><div class="line"><span class="keyword">namespace </span>hana = <a class="code" href="namespaceboost_1_1hana.html">boost::hana</a>;</div><div class="line"></div><div class="line"></div><div class="line">BOOST_HANA_CONSTEXPR_LAMBDA <span class="keyword">auto</span> deref = [](<span class="keyword">auto</span> x) -&gt; decltype(*x) {</div><div class="line"> <span class="keywordflow">return</span> *x;</div><div class="line">};</div><div class="line"></div><div class="line">BOOST_HANA_CONSTEXPR_LAMBDA <span class="keyword">auto</span> age = [](<span class="keyword">auto</span> x) -&gt; decltype(x.age) {</div><div class="line"> <span class="keywordflow">return</span> x.age;</div><div class="line">};</div><div class="line"></div><div class="line">BOOST_HANA_CONSTEXPR_LAMBDA <span class="keyword">auto</span> f = [](<span class="keyword">auto</span> x) {</div><div class="line"> <span class="keywordflow">return</span> <a class="code" href="group__group-Monad.html#ga05fdc2f887cb9967357487a432ace98b">hana::chain</a>(hana::sfinae(deref)(x), hana::sfinae(age));</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">struct </span>Person {</div><div class="line"> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> age;</div><div class="line"> <span class="comment">// ...</span></div><div class="line">};</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main() {</div><div class="line"> constexpr Person john{30};</div><div class="line"></div><div class="line"> <span class="comment">// Can&#39;t dereference a non-pointer.</span></div><div class="line"> <a class="code" href="group__group-assertions.html#ga2c5006540936d9f8880e3a39f4fcc035">BOOST_HANA_CONSTANT_CHECK</a>(f(john) == hana::nothing);</div><div class="line"></div><div class="line"> <span class="comment">// `int` has no member named `age`.</span></div><div class="line"> <a class="code" href="group__group-assertions.html#ga2c5006540936d9f8880e3a39f4fcc035">BOOST_HANA_CONSTANT_CHECK</a>(f(1) == hana::nothing);</div><div class="line"></div><div class="line"> <span class="comment">// All is good.</span></div><div class="line"> <a class="code" href="group__group-assertions.html#gac7aafc41e4dcc7d1f1929fb00f010d2a">BOOST_HANA_CONSTEXPR_CHECK</a>(f(&amp;john) == hana::just(30u));</div><div class="line">}</div></div><!-- fragment -->
  205. </div>
  206. </div>
  207. <a id="gaa5fec6fb418de5da3ecb500fd6cc54dd"></a>
  208. <h2 class="memtitle"><span class="permalink"><a href="#gaa5fec6fb418de5da3ecb500fd6cc54dd">&#9670;&nbsp;</a></span>flatten</h2>
  209. <div class="memitem">
  210. <div class="memproto">
  211. <table class="memname">
  212. <tr>
  213. <td class="memname">constexpr auto boost::hana::flatten</td>
  214. </tr>
  215. </table>
  216. </div><div class="memdoc">
  217. <p><code>#include &lt;<a class="el" href="fwd_2flatten_8hpp.html">boost/hana/fwd/flatten.hpp</a>&gt;</code></p>
  218. <b>Initial value:</b><div class="fragment"><div class="line">= [](<span class="keyword">auto</span>&amp;&amp; xs) {</div><div class="line"> <span class="keywordflow">return</span> tag-dispatched;</div><div class="line"> }</div></div><!-- fragment -->
  219. <p>Collapse two levels of monadic structure into a single level.Given a monadic value wrapped into two levels of monad, <code>flatten</code> removes one such level. An implementation of <code>flatten</code> must satisfy. </p>
  220. <div class="fragment"><div class="line"><a class="code" href="group__group-Monad.html#gaa5fec6fb418de5da3ecb500fd6cc54dd">flatten</a>(xs) == <a class="code" href="group__group-Monad.html#ga05fdc2f887cb9967357487a432ace98b">chain</a>(xs, <span class="keywordtype">id</span>)</div></div><!-- fragment --><p>For <code>Sequence</code>s, this simply takes a <code>Sequence</code> of <code>Sequence</code>s, and returns a (non-recursively) flattened <code>Sequence</code>.</p>
  221. <h2>Signature </h2>
  222. <p>For a <code>Monad</code> <code>M</code>, the signature of <code>flatten</code> is \( \mathtt{flatten} : M(M(T)) \to M(T) \)</p>
  223. <dl class="params"><dt>Parameters</dt><dd>
  224. <table class="params">
  225. <tr><td class="paramname">xs</td><td>A value with two levels of monadic structure, which should be collapsed into a single level of structure.</td></tr>
  226. </table>
  227. </dd>
  228. </dl>
  229. <h2>Example </h2>
  230. <div class="fragment"><div class="line"><span class="comment">// Copyright Louis Dionne 2013-2017</span></div><div class="line"><span class="comment">// Distributed under the Boost Software License, Version 1.0.</span></div><div class="line"><span class="comment">// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="assert_8hpp.html">boost/hana/assert.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="equal_8hpp.html">boost/hana/equal.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="flatten_8hpp.html">boost/hana/flatten.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="optional_8hpp.html">boost/hana/optional.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="tuple_8hpp.html">boost/hana/tuple.hpp</a>&gt;</span></div><div class="line"><span class="keyword">namespace </span>hana = <a class="code" href="namespaceboost_1_1hana.html">boost::hana</a>;</div><div class="line"></div><div class="line"></div><div class="line">static_assert(</div><div class="line"> <a class="code" href="group__group-Monad.html#gaa5fec6fb418de5da3ecb500fd6cc54dd">hana::flatten</a>(hana::make_tuple(hana::make_tuple(1, 2, 3),</div><div class="line"> hana::make_tuple(4, 5),</div><div class="line"> hana::make_tuple(6, 7, 8, 9)))</div><div class="line"> ==</div><div class="line"> hana::make_tuple(1, 2, 3, 4, 5, 6, 7, 8, 9)</div><div class="line">, <span class="stringliteral">&quot;&quot;</span>);</div><div class="line"></div><div class="line"><a class="code" href="group__group-assertions.html#ga2c5006540936d9f8880e3a39f4fcc035">BOOST_HANA_CONSTANT_CHECK</a>(<a class="code" href="group__group-Monad.html#gaa5fec6fb418de5da3ecb500fd6cc54dd">hana::flatten</a>(hana::nothing) == hana::nothing);</div><div class="line">static_assert(<a class="code" href="group__group-Monad.html#gaa5fec6fb418de5da3ecb500fd6cc54dd">hana::flatten</a>(hana::just(hana::just(1))) == hana::just(1), <span class="stringliteral">&quot;&quot;</span>);</div><div class="line"><a class="code" href="group__group-assertions.html#ga2c5006540936d9f8880e3a39f4fcc035">BOOST_HANA_CONSTANT_CHECK</a>(<a class="code" href="group__group-Monad.html#gaa5fec6fb418de5da3ecb500fd6cc54dd">hana::flatten</a>(hana::just(hana::nothing)) == hana::nothing);</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main() { }</div></div><!-- fragment -->
  231. </div>
  232. </div>
  233. <a id="gaec3fe26c7378fd3057af83e03bd9b104"></a>
  234. <h2 class="memtitle"><span class="permalink"><a href="#gaec3fe26c7378fd3057af83e03bd9b104">&#9670;&nbsp;</a></span>monadic_compose</h2>
  235. <div class="memitem">
  236. <div class="memproto">
  237. <table class="memname">
  238. <tr>
  239. <td class="memname">constexpr auto boost::hana::monadic_compose</td>
  240. </tr>
  241. </table>
  242. </div><div class="memdoc">
  243. <p><code>#include &lt;<a class="el" href="fwd_2monadic__compose_8hpp.html">boost/hana/fwd/monadic_compose.hpp</a>&gt;</code></p>
  244. <b>Initial value:</b><div class="fragment"><div class="line">= [](<span class="keyword">auto</span>&amp;&amp; f, <span class="keyword">auto</span>&amp;&amp; g) {</div><div class="line"> <span class="keywordflow">return</span> [perfect-<a class="code" href="group__group-functional.html#ga41ada6b336e9d5bcb101ff0c737acbd0">capture</a>](<span class="keyword">auto</span>&amp;&amp; x) -&gt; decltype(<span class="keyword">auto</span>) {</div><div class="line"> <span class="keywordflow">return</span> <a class="code" href="group__group-Monad.html#ga05fdc2f887cb9967357487a432ace98b">hana::chain</a>(forwarded(g)(forwarded(x)), forwarded(f));</div><div class="line"> };</div><div class="line"> }</div><div class="ttc" id="group__group-Monad_html_ga05fdc2f887cb9967357487a432ace98b"><div class="ttname"><a href="group__group-Monad.html#ga05fdc2f887cb9967357487a432ace98b">boost::hana::chain</a></div><div class="ttdeci">constexpr auto chain</div><div class="ttdoc">Feed a monadic value into a monadic computation.Given a monadic value and a monadic function,...</div><div class="ttdef"><b>Definition:</b> chain.hpp:51</div></div>
  245. <div class="ttc" id="group__group-functional_html_ga41ada6b336e9d5bcb101ff0c737acbd0"><div class="ttname"><a href="group__group-functional.html#ga41ada6b336e9d5bcb101ff0c737acbd0">boost::hana::capture</a></div><div class="ttdeci">constexpr auto capture</div><div class="ttdoc">Create a function capturing the given variables.</div><div class="ttdef"><b>Definition:</b> capture.hpp:45</div></div>
  246. </div><!-- fragment -->
  247. <p>Composition of monadic functions.Given two monadic functions <code>f</code> and <code>g</code>, <code>monadic_compose</code> returns a new function equivalent to the composition of <code>f</code> with <code>g</code>, except the result of <code>g</code> is <code>chain</code>ed into <code>f</code> instead of simply passed to it, as with normal composition. <code>monadic_compose</code> satisfies. </p>
  248. <div class="fragment"><div class="line"><a class="code" href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">monadic_compose</a>(f, g)(x) == <a class="code" href="group__group-Monad.html#ga05fdc2f887cb9967357487a432ace98b">chain</a>(g(x), f)</div></div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>Unlike <code>compose</code>, <code>monadic_compose</code> does not generalize nicely to arities higher than one. Hence, only unary functions may be used with <code>monadic_compose</code>.</dd></dl>
  249. <h2>Signature </h2>
  250. <p>Given a <code>Monad</code> <code>M</code> and two functions \( f : B \to M(C) \) and \( g : A \to M(B) \), the signature is \( \mathtt{monadic\_compose} : (B \to M(C)) \times (A \to M(B)) \to (A \to M(C)) \).</p>
  251. <dl class="params"><dt>Parameters</dt><dd>
  252. <table class="params">
  253. <tr><td class="paramname">f</td><td>A monadic function with signature \( B \to M(C) \).</td></tr>
  254. <tr><td class="paramname">g</td><td>A monadic function with signature \( A \to M(B) \).</td></tr>
  255. </table>
  256. </dd>
  257. </dl>
  258. <dl class="section note"><dt>Note</dt><dd>This method is not tag-dispatched, so it can't be customized directly.</dd></dl>
  259. <h2>Example </h2>
  260. <div class="fragment"><div class="line"><span class="comment">// Copyright Louis Dionne 2013-2017</span></div><div class="line"><span class="comment">// Distributed under the Boost Software License, Version 1.0.</span></div><div class="line"><span class="comment">// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="assert_8hpp.html">boost/hana/assert.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="config_8hpp.html">boost/hana/config.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="contains_8hpp.html">boost/hana/contains.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="equal_8hpp.html">boost/hana/equal.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="if_8hpp.html">boost/hana/if.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="monadic__compose_8hpp.html">boost/hana/monadic_compose.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="optional_8hpp.html">boost/hana/optional.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="tuple_8hpp.html">boost/hana/tuple.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="type_8hpp.html">boost/hana/type.hpp</a>&gt;</span></div><div class="line"><span class="keyword">namespace </span>hana = <a class="code" href="namespaceboost_1_1hana.html">boost::hana</a>;</div><div class="line"></div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main() {</div><div class="line"> BOOST_HANA_CONSTEXPR_LAMBDA <span class="keyword">auto</span> block = [](<span class="keyword">auto</span> ...types) {</div><div class="line"> <span class="keywordflow">return</span> [=](<span class="keyword">auto</span> x) {</div><div class="line"> <span class="keywordflow">return</span> <a class="code" href="group__group-Logical.html#gafd655d2222367131e7a63616e93dd080">hana::if_</a>(<a class="code" href="group__group-Searchable.html#ga38e7748956cbc9f3d9bb035ac8577906">hana::contains</a>(hana::make_tuple(types...), hana::typeid_(x)),</div><div class="line"> hana::nothing,</div><div class="line"> hana::just(x)</div><div class="line"> );</div><div class="line"> };</div><div class="line"> };</div><div class="line"></div><div class="line"> BOOST_HANA_CONSTEXPR_LAMBDA <span class="keyword">auto</span> f = block(hana::type_c&lt;double&gt;);</div><div class="line"> BOOST_HANA_CONSTEXPR_LAMBDA <span class="keyword">auto</span> g = block(hana::type_c&lt;int&gt;);</div><div class="line"> BOOST_HANA_CONSTEXPR_LAMBDA <span class="keyword">auto</span> h = <a class="code" href="group__group-Monad.html#gaec3fe26c7378fd3057af83e03bd9b104">hana::monadic_compose</a>(g, f);</div><div class="line"> <a class="code" href="group__group-assertions.html#ga2c5006540936d9f8880e3a39f4fcc035">BOOST_HANA_CONSTANT_CHECK</a>(h(1) == hana::nothing); <span class="comment">// fails inside g; 1 has type int</span></div><div class="line"> <a class="code" href="group__group-assertions.html#ga2c5006540936d9f8880e3a39f4fcc035">BOOST_HANA_CONSTANT_CHECK</a>(h(1.2) == hana::nothing); <span class="comment">// fails inside f; 1.2 has type double</span></div><div class="line"> <a class="code" href="group__group-assertions.html#gac7aafc41e4dcc7d1f1929fb00f010d2a">BOOST_HANA_CONSTEXPR_CHECK</a>(h(<span class="charliteral">&#39;x&#39;</span>) == hana::just(<span class="charliteral">&#39;x&#39;</span>)); <span class="comment">// ok; &#39;x&#39; has type char</span></div><div class="line">}</div></div><!-- fragment -->
  261. </div>
  262. </div>
  263. <a id="ga5e0735de01a24f681c55aedfeb6d13bf"></a>
  264. <h2 class="memtitle"><span class="permalink"><a href="#ga5e0735de01a24f681c55aedfeb6d13bf">&#9670;&nbsp;</a></span>tap</h2>
  265. <div class="memitem">
  266. <div class="memproto">
  267. <div class="memtemplate">
  268. template&lt;typename M &gt; </div>
  269. <table class="memname">
  270. <tr>
  271. <td class="memname">constexpr auto boost::hana::tap</td>
  272. </tr>
  273. </table>
  274. </div><div class="memdoc">
  275. <p><code>#include &lt;<a class="el" href="fwd_2tap_8hpp.html">boost/hana/fwd/tap.hpp</a>&gt;</code></p>
  276. <b>Initial value:</b><div class="fragment"><div class="line">= [](<span class="keyword">auto</span>&amp;&amp; f) {</div><div class="line"> <span class="keywordflow">return</span> tag-dispatched;</div><div class="line"> }</div></div><!-- fragment -->
  277. <p>Tap inside a monadic chain.Given a function <code>f</code>, <code>tap&lt;M&gt;</code> returns a new function which performs <code>f</code> on its argument and then returns the argument lifted in the <code>M</code> <code>Monad</code>. Combined with the property that <code>chain(m, lift&lt;M&gt;) == m</code>, this provides a way of executing an action inside a monadic chain without influencing its overall result. This is useful to e.g. insert debug statements or perform actions that are not tied to the chain but that need to be executed inside of it. </p>
  278. <dl class="section note"><dt>Note</dt><dd>Since C++ is not a pure language, it is possible to perform side effects inside the <code>f</code> function. Actually, side effects are the only reason why one might want to use <code>tap</code>. However, one should not rely on the side effects being done in any specific order.</dd></dl>
  279. <dl class="tparams"><dt>Template Parameters</dt><dd>
  280. <table class="tparams">
  281. <tr><td class="paramname">M</td><td>The tag (a <code>Monad</code>) of the monads in the tapped monadic chain.</td></tr>
  282. </table>
  283. </dd>
  284. </dl>
  285. <dl class="params"><dt>Parameters</dt><dd>
  286. <table class="params">
  287. <tr><td class="paramname">f</td><td>A function to be executed inside a monadic chain. It will be called as <code>f(x)</code>, where <code>x</code> is a value inside the previous monad in the chain. The result of <code>f</code> is always discarded.</td></tr>
  288. </table>
  289. </dd>
  290. </dl>
  291. <h2>Example </h2>
  292. <div class="fragment"><div class="line"><span class="comment">// Copyright Louis Dionne 2013-2017</span></div><div class="line"><span class="comment">// Distributed under the Boost Software License, Version 1.0.</span></div><div class="line"><span class="comment">// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="assert_8hpp.html">boost/hana/assert.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="chain_8hpp.html">boost/hana/chain.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="equal_8hpp.html">boost/hana/equal.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="tap_8hpp.html">boost/hana/tap.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="tuple_8hpp.html">boost/hana/tuple.hpp</a>&gt;</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;set&gt;</span></div><div class="line"><span class="keyword">namespace </span>hana = <a class="code" href="namespaceboost_1_1hana.html">boost::hana</a>;</div><div class="line"></div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main() {</div><div class="line"> <span class="comment">// We use a sorted container because the order in which the functions</span></div><div class="line"> <span class="comment">// are called is unspecified.</span></div><div class="line"> std::set&lt;int&gt; before, after;</div><div class="line"></div><div class="line"> <span class="keyword">auto</span> xs = hana::make_tuple(1, 2, 3)</div><div class="line"> | hana::tap&lt;hana::tuple_tag&gt;([&amp;](<span class="keywordtype">int</span> x) { before.insert(x); })</div><div class="line"> | [](<span class="keyword">auto</span> x) { <span class="keywordflow">return</span> hana::make_tuple(x, -x); }</div><div class="line"> | hana::tap&lt;hana::tuple_tag&gt;([&amp;](<span class="keywordtype">int</span> x) { after.insert(x); });</div><div class="line"></div><div class="line"> <a class="code" href="group__group-assertions.html#ga4796ae107d58b67e0bbccd5ae6f70101">BOOST_HANA_RUNTIME_CHECK</a>(before == std::set&lt;int&gt;{1, 2, 3});</div><div class="line"> <a class="code" href="group__group-assertions.html#ga4796ae107d58b67e0bbccd5ae6f70101">BOOST_HANA_RUNTIME_CHECK</a>(after == std::set&lt;int&gt;{1, -1, 2, -2, 3, -3});</div><div class="line"> <a class="code" href="group__group-assertions.html#ga4796ae107d58b67e0bbccd5ae6f70101">BOOST_HANA_RUNTIME_CHECK</a>(xs == hana::make_tuple(1, -1, 2, -2, 3, -3));</div><div class="line">}</div></div><!-- fragment -->
  293. </div>
  294. </div>
  295. <a id="gaaddd3789de43cf989babb10cdc0b447a"></a>
  296. <h2 class="memtitle"><span class="permalink"><a href="#gaaddd3789de43cf989babb10cdc0b447a">&#9670;&nbsp;</a></span>then</h2>
  297. <div class="memitem">
  298. <div class="memproto">
  299. <table class="memname">
  300. <tr>
  301. <td class="memname">constexpr auto boost::hana::then</td>
  302. </tr>
  303. </table>
  304. </div><div class="memdoc">
  305. <p><code>#include &lt;<a class="el" href="fwd_2then_8hpp.html">boost/hana/fwd/then.hpp</a>&gt;</code></p>
  306. <b>Initial value:</b><div class="fragment"><div class="line">= [](<span class="keyword">auto</span>&amp;&amp; before, <span class="keyword">auto</span>&amp;&amp; xs) -&gt; decltype(<span class="keyword">auto</span>) {</div><div class="line"> <span class="keywordflow">return</span> tag-dispatched;</div><div class="line"> }</div></div><!-- fragment -->
  307. <p>Sequentially compose two monadic actions, discarding any value produced by the first but not its effects. </p>
  308. <dl class="params"><dt>Parameters</dt><dd>
  309. <table class="params">
  310. <tr><td class="paramname">before</td><td>The first <code>Monad</code> in the monadic composition chain. The result of this monad is ignored, but its effects are combined with that of the second monad.</td></tr>
  311. <tr><td class="paramname">xs</td><td>The second <code>Monad</code> in the monadic composition chain.</td></tr>
  312. </table>
  313. </dd>
  314. </dl>
  315. <h2>Example </h2>
  316. <div class="fragment"><div class="line"><span class="comment">// Copyright Louis Dionne 2013-2017</span></div><div class="line"><span class="comment">// Distributed under the Boost Software License, Version 1.0.</span></div><div class="line"><span class="comment">// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="equal_8hpp.html">boost/hana/equal.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="then_8hpp.html">boost/hana/then.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="tuple_8hpp.html">boost/hana/tuple.hpp</a>&gt;</span></div><div class="line"><span class="keyword">namespace </span>hana = <a class="code" href="namespaceboost_1_1hana.html">boost::hana</a>;</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">struct </span>undefined { };</div><div class="line">static_assert(</div><div class="line"> <a class="code" href="group__group-Monad.html#gaaddd3789de43cf989babb10cdc0b447a">hana::then</a>(hana::make_tuple(undefined{}, undefined{}), hana::make_tuple(1, 2, 3))</div><div class="line"> ==</div><div class="line"> hana::make_tuple(</div><div class="line"> 1, 2, 3,</div><div class="line"> 1, 2, 3</div><div class="line"> )</div><div class="line">, <span class="stringliteral">&quot;&quot;</span>);</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main() { }</div></div><!-- fragment -->
  317. </div>
  318. </div>
  319. </div><!-- contents -->
  320. </div><!-- doc-content -->
  321. <!--
  322. Copyright Louis Dionne 2013-2017
  323. Distributed under the Boost Software License, Version 1.0.
  324. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  325. -->
  326. <!-- boost-no-inspect -->
  327. <!-- HTML footer for doxygen 1.8.9.1-->
  328. <!-- start footer part -->
  329. <div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  330. <ul>
  331. </ul>
  332. </div>
  333. </body>
  334. </html>