monad.hpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*!
  2. @file
  3. Forward declares `boost::hana::Monad`.
  4. @copyright Louis Dionne 2013-2017
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_FWD_CONCEPT_MONAD_HPP
  9. #define BOOST_HANA_FWD_CONCEPT_MONAD_HPP
  10. #include <boost/hana/config.hpp>
  11. BOOST_HANA_NAMESPACE_BEGIN
  12. //! @ingroup group-concepts
  13. //! @defgroup group-Monad Monad
  14. //! The `Monad` concept represents `Applicative`s with the ability to
  15. //! flatten nested levels of structure.
  16. //!
  17. //! Historically, Monads are a construction coming from category theory,
  18. //! an abstract branch of mathematics. The functional programming
  19. //! community eventually discovered how Monads could be used to
  20. //! formalize several useful things like side effects, which led
  21. //! to the wide adoption of Monads in that community. However, even
  22. //! in a multi-paradigm language like C++, there are several constructs
  23. //! which turn out to be Monads, like `std::optional`, `std::vector` and
  24. //! others.
  25. //!
  26. //! Everybody tries to introduce `Monad`s with a different analogy, and
  27. //! most people fail. This is called the [Monad tutorial fallacy][1]. We
  28. //! will try to avoid this trap by not presenting a specific intuition,
  29. //! and we will instead present what monads are mathematically.
  30. //! For specific intuitions, we will let readers who are new to this
  31. //! concept read one of the many excellent tutorials available online.
  32. //! Understanding Monads might take time at first, but once you get it,
  33. //! a lot of patterns will become obvious Monads; this enlightening will
  34. //! be your reward for the hard work.
  35. //!
  36. //! There are different ways of defining a Monad; Haskell uses a function
  37. //! called `bind` (`>>=`) and another one called `return` (it has nothing
  38. //! to do with C++'s `return` statement). They then introduce relationships
  39. //! that must be satisfied for a type to be a Monad with those functions.
  40. //! Mathematicians sometimes use a function called `join` and another one
  41. //! called `unit`, or they also sometimes use other category theoretic
  42. //! constructions like functor adjunctions and the Kleisli category.
  43. //!
  44. //! This library uses a composite approach. First, we use the `flatten`
  45. //! function (equivalent to `join`) along with the `lift` function from
  46. //! `Applicative` (equivalent to `unit`) to introduce the notion of
  47. //! monadic function composition. We then write the properties that must
  48. //! be satisfied by a Monad using this monadic composition operator,
  49. //! because we feel it shows the link between Monads and Monoids more
  50. //! clearly than other approaches.
  51. //!
  52. //! Roughly speaking, we will say that a `Monad` is an `Applicative` which
  53. //! also defines a way to compose functions returning a monadic result,
  54. //! as opposed to only being able to compose functions returning a normal
  55. //! result. We will then ask for this composition to be associative and to
  56. //! have a neutral element, just like normal function composition. For
  57. //! usual composition, the neutral element is the identity function `id`.
  58. //! For monadic composition, the neutral element is the `lift` function
  59. //! defined by `Applicative`. This construction is made clearer in the
  60. //! laws below.
  61. //!
  62. //! @note
  63. //! Monads are known to be a big chunk to swallow. However, it is out of
  64. //! the scope of this documentation to provide a full-blown explanation
  65. //! of the concept. The [Typeclassopedia][2] is a nice Haskell-oriented
  66. //! resource where more information about Monads can be found.
  67. //!
  68. //!
  69. //! Minimal complete definitions
  70. //! ----------------------------
  71. //! First, a `Monad` must be both a `Functor` and an `Applicative`.
  72. //! Also, an implementation of `flatten` or `chain` satisfying the
  73. //! laws below for monadic composition must be provided.
  74. //!
  75. //! @note
  76. //! The `ap` method for `Applicatives` may be derived from the minimal
  77. //! complete definition of `Monad` and `Functor`; see below for more
  78. //! information.
  79. //!
  80. //!
  81. //! Laws
  82. //! ----
  83. //! To simplify writing the laws, we use the comparison between functions.
  84. //! For two functions `f` and `g`, we define
  85. //! @code
  86. //! f == g if and only if f(x) == g(x) for all x
  87. //! @endcode
  88. //!
  89. //! With the usual composition of functions, we are given two functions
  90. //! @f$ f : A \to B @f$ and @f$ g : B \to C @f$, and we must produce a
  91. //! new function @f$ compose(g, f) : A \to C @f$. This composition of
  92. //! functions is associative, which means that
  93. //! @code
  94. //! compose(h, compose(g, f)) == compose(compose(h, g), f)
  95. //! @endcode
  96. //!
  97. //! Also, this composition has an identity element, which is the identity
  98. //! function. This simply means that
  99. //! @code
  100. //! compose(f, id) == compose(id, f) == f
  101. //! @endcode
  102. //!
  103. //! This is probably nothing new if you are reading the `Monad` laws.
  104. //! Now, we can observe that the above is equivalent to saying that
  105. //! functions with the composition operator form a `Monoid`, where the
  106. //! neutral element is the identity function.
  107. //!
  108. //! Given an `Applicative` `F`, what if we wanted to compose two functions
  109. //! @f$ f : A \to F(B) @f$ and @f$ g : B \to F(C) @f$? When the
  110. //! `Applicative` `F` is also a `Monad`, such functions taking normal
  111. //! values but returning monadic values are called _monadic functions_.
  112. //! To compose them, we obviously can't use normal function composition,
  113. //! since the domains and codomains of `f` and `g` do not match properly.
  114. //! Instead, we'll need a new operator -- let's call it `monadic_compose`:
  115. //! @f[
  116. //! \mathtt{monadic\_compose} :
  117. //! (B \to F(C)) \times (A \to F(B)) \to (A \to F(C))
  118. //! @f]
  119. //!
  120. //! How could we go about implementing this function? Well, since we know
  121. //! `F` is an `Applicative`, the only functions we have are `transform`
  122. //! (from `Functor`), and `lift` and `ap` (from `Applicative`). Hence,
  123. //! the only thing we can do at this point while respecting the signatures
  124. //! of `f` and `g` is to set (for `x` of type `A`)
  125. //! @code
  126. //! monadic_compose(g, f)(x) = transform(f(x), g)
  127. //! @endcode
  128. //!
  129. //! Indeed, `f(x)` is of type `F(B)`, so we can map `g` (which takes `B`'s)
  130. //! on it. Doing so will leave us with a result of type `F(F(C))`, but what
  131. //! we wanted was a result of type `F(C)` to respect the signature of
  132. //! `monadic_compose`. If we had a joker of type @f$ F(F(C)) \to F(C) @f$,
  133. //! we could simply set
  134. //! @code
  135. //! monadic_compose(g, f)(x) = joker(transform(f(x), g))
  136. //! @endcode
  137. //!
  138. //! and we would be happy. It turns out that `flatten` is precisely this
  139. //! joker. Now, we'll want our joker to satisfy some properties to make
  140. //! sure this composition is associative, just like our normal composition
  141. //! was. These properties are slightly cumbersome to specify, so we won't
  142. //! do it here. Also, we'll need some kind of neutral element for the
  143. //! composition. This neutral element can't be the usual identity function,
  144. //! because it does not have the right type: our neutral element needs to
  145. //! be a function of type @f$ X \to F(X) @f$ but the identity function has
  146. //! type @f$ X \to X @f$. It is now the right time to observe that `lift`
  147. //! from `Applicative` has exactly the right signature, and so we'll take
  148. //! this for our neutral element.
  149. //!
  150. //! We are now ready to formulate the `Monad` laws using this composition
  151. //! operator. For a `Monad` `M` and functions @f$ f : A \to M(B) @f$,
  152. //! @f$ g : B \to M(C) @f$ and @f$ h : C \to M(D) @f$, the following
  153. //! must be satisfied:
  154. //! @code
  155. //! // associativity
  156. //! monadic_compose(h, monadic_compose(g, f)) == monadic_compose(monadic_compose(h, g), f)
  157. //!
  158. //! // right identity
  159. //! monadic_compose(f, lift<M(A)>) == f
  160. //!
  161. //! // left identity
  162. //! monadic_compose(lift<M(B)>, f) == f
  163. //! @endcode
  164. //!
  165. //! which is to say that `M` along with monadic composition is a Monoid
  166. //! where the neutral element is `lift`.
  167. //!
  168. //!
  169. //! Refined concepts
  170. //! ----------------
  171. //! 1. `Functor`
  172. //! 2. `Applicative` (free implementation of `ap`)\n
  173. //! When the minimal complete definition for `Monad` and `Functor` are
  174. //! both satisfied, it is possible to implement `ap` by setting
  175. //! @code
  176. //! ap(fs, xs) = chain(fs, [](auto f) {
  177. //! return transform(xs, f);
  178. //! })
  179. //! @endcode
  180. //!
  181. //!
  182. //! Concrete models
  183. //! ---------------
  184. //! `hana::lazy`, `hana::optional`, `hana::tuple`
  185. //!
  186. //!
  187. //! [1]: https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/
  188. //! [2]: https://wiki.haskell.org/Typeclassopedia#Monad
  189. template <typename M>
  190. struct Monad;
  191. BOOST_HANA_NAMESPACE_END
  192. #endif // !BOOST_HANA_FWD_CONCEPT_MONAD_HPP