Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:58

0001 /*!
0002 @file
0003 Forward declares `boost::hana::Monad`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0008  */
0009 
0010 #ifndef BOOST_HANA_FWD_CONCEPT_MONAD_HPP
0011 #define BOOST_HANA_FWD_CONCEPT_MONAD_HPP
0012 
0013 #include <boost/hana/config.hpp>
0014 
0015 
0016 namespace boost { namespace hana {
0017     //! @ingroup group-concepts
0018     //! @defgroup group-Monad Monad
0019     //! The `Monad` concept represents `Applicative`s with the ability to
0020     //! flatten nested levels of structure.
0021     //!
0022     //! Historically, Monads are a construction coming from category theory,
0023     //! an abstract branch of mathematics. The functional programming
0024     //! community eventually discovered how Monads could be used to
0025     //! formalize several useful things like side effects, which led
0026     //! to the wide adoption of Monads in that community. However, even
0027     //! in a multi-paradigm language like C++, there are several constructs
0028     //! which turn out to be Monads, like `std::optional`, `std::vector` and
0029     //! others.
0030     //!
0031     //! Everybody tries to introduce `Monad`s with a different analogy, and
0032     //! most people fail. This is called the [Monad tutorial fallacy][1]. We
0033     //! will try to avoid this trap by not presenting a specific intuition,
0034     //! and we will instead present what monads are mathematically.
0035     //! For specific intuitions, we will let readers who are new to this
0036     //! concept read one of the many excellent tutorials available online.
0037     //! Understanding Monads might take time at first, but once you get it,
0038     //! a lot of patterns will become obvious Monads; this enlightening will
0039     //! be your reward for the hard work.
0040     //!
0041     //! There are different ways of defining a Monad; Haskell uses a function
0042     //! called `bind` (`>>=`) and another one called `return` (it has nothing
0043     //! to do with C++'s `return` statement). They then introduce relationships
0044     //! that must be satisfied for a type to be a Monad with those functions.
0045     //! Mathematicians sometimes use a function called `join` and another one
0046     //! called `unit`, or they also sometimes use other category theoretic
0047     //! constructions like functor adjunctions and the Kleisli category.
0048     //!
0049     //! This library uses a composite approach. First, we use the `flatten`
0050     //! function (equivalent to `join`) along with the `lift` function from
0051     //! `Applicative` (equivalent to `unit`) to introduce the notion of
0052     //! monadic function composition. We then write the properties that must
0053     //! be satisfied by a Monad using this monadic composition operator,
0054     //! because we feel it shows the link between Monads and Monoids more
0055     //! clearly than other approaches.
0056     //!
0057     //! Roughly speaking, we will say that a `Monad` is an `Applicative` which
0058     //! also defines a way to compose functions returning a monadic result,
0059     //! as opposed to only being able to compose functions returning a normal
0060     //! result. We will then ask for this composition to be associative and to
0061     //! have a neutral element, just like normal function composition. For
0062     //! usual composition, the neutral element is the identity function `id`.
0063     //! For monadic composition, the neutral element is the `lift` function
0064     //! defined by `Applicative`. This construction is made clearer in the
0065     //! laws below.
0066     //!
0067     //! @note
0068     //! Monads are known to be a big chunk to swallow. However, it is out of
0069     //! the scope of this documentation to provide a full-blown explanation
0070     //! of the concept. The [Typeclassopedia][2] is a nice Haskell-oriented
0071     //! resource where more information about Monads can be found.
0072     //!
0073     //!
0074     //! Minimal complete definitions
0075     //! ----------------------------
0076     //! First, a `Monad` must be both a `Functor` and an `Applicative`.
0077     //! Also, an implementation of `flatten` or `chain` satisfying the
0078     //! laws below for monadic composition must be provided.
0079     //!
0080     //! @note
0081     //! The `ap` method for `Applicatives` may be derived from the minimal
0082     //! complete definition of `Monad` and `Functor`; see below for more
0083     //! information.
0084     //!
0085     //!
0086     //! Laws
0087     //! ----
0088     //! To simplify writing the laws, we use the comparison between functions.
0089     //! For two functions `f` and `g`, we define
0090     //! @code
0091     //!     f == g  if and only if  f(x) == g(x) for all x
0092     //! @endcode
0093     //!
0094     //! With the usual composition of functions, we are given two functions
0095     //! @f$ f : A \to B @f$ and @f$ g : B \to C @f$, and we must produce a
0096     //! new function @f$ compose(g, f) : A \to C @f$. This composition of
0097     //! functions is associative, which means that
0098     //! @code
0099     //!     compose(h, compose(g, f)) == compose(compose(h, g), f)
0100     //! @endcode
0101     //!
0102     //! Also, this composition has an identity element, which is the identity
0103     //! function. This simply means that
0104     //! @code
0105     //!     compose(f, id) == compose(id, f) == f
0106     //! @endcode
0107     //!
0108     //! This is probably nothing new if you are reading the `Monad` laws.
0109     //! Now, we can observe that the above is equivalent to saying that
0110     //! functions with the composition operator form a `Monoid`, where the
0111     //! neutral element is the identity function.
0112     //!
0113     //! Given an `Applicative` `F`, what if we wanted to compose two functions
0114     //! @f$ f : A \to F(B) @f$ and @f$ g : B \to F(C) @f$? When the
0115     //! `Applicative` `F` is also a `Monad`, such functions taking normal
0116     //! values but returning monadic values are called _monadic functions_.
0117     //! To compose them, we obviously can't use normal function composition,
0118     //! since the domains and codomains of `f` and `g` do not match properly.
0119     //! Instead, we'll need a new operator -- let's call it `monadic_compose`:
0120     //! @f[
0121     //!     \mathtt{monadic\_compose} :
0122     //!         (B \to F(C)) \times (A \to F(B)) \to (A \to F(C))
0123     //! @f]
0124     //!
0125     //! How could we go about implementing this function? Well, since we know
0126     //! `F` is an `Applicative`, the only functions we have are `transform`
0127     //! (from `Functor`), and `lift` and `ap` (from `Applicative`). Hence,
0128     //! the only thing we can do at this point while respecting the signatures
0129     //! of `f` and `g` is to set (for `x` of type `A`)
0130     //! @code
0131     //!     monadic_compose(g, f)(x) = transform(f(x), g)
0132     //! @endcode
0133     //!
0134     //! Indeed, `f(x)` is of type `F(B)`, so we can map `g` (which takes `B`'s)
0135     //! on it. Doing so will leave us with a result of type `F(F(C))`, but what
0136     //! we wanted was a result of type `F(C)` to respect the signature of
0137     //! `monadic_compose`. If we had a joker of type @f$ F(F(C)) \to F(C) @f$,
0138     //! we could simply set
0139     //! @code
0140     //!     monadic_compose(g, f)(x) = joker(transform(f(x), g))
0141     //! @endcode
0142     //!
0143     //! and we would be happy. It turns out that `flatten` is precisely this
0144     //! joker. Now, we'll want our joker to satisfy some properties to make
0145     //! sure this composition is associative, just like our normal composition
0146     //! was. These properties are slightly cumbersome to specify, so we won't
0147     //! do it here. Also, we'll need some kind of neutral element for the
0148     //! composition. This neutral element can't be the usual identity function,
0149     //! because it does not have the right type: our neutral element needs to
0150     //! be a function of type @f$ X \to F(X) @f$ but the identity function has
0151     //! type @f$ X \to X @f$. It is now the right time to observe that `lift`
0152     //! from `Applicative` has exactly the right signature, and so we'll take
0153     //! this for our neutral element.
0154     //!
0155     //! We are now ready to formulate the `Monad` laws using this composition
0156     //! operator. For a `Monad` `M` and functions @f$ f : A \to M(B) @f$,
0157     //! @f$ g : B \to M(C) @f$ and @f$ h : C \to M(D) @f$, the following
0158     //! must be satisfied:
0159     //! @code
0160     //!     // associativity
0161     //!     monadic_compose(h, monadic_compose(g, f)) == monadic_compose(monadic_compose(h, g), f)
0162     //!
0163     //!     // right identity
0164     //!     monadic_compose(f, lift<M(A)>) == f
0165     //!
0166     //!     // left identity
0167     //!     monadic_compose(lift<M(B)>, f) == f
0168     //! @endcode
0169     //!
0170     //! which is to say that `M` along with monadic composition is a Monoid
0171     //! where the neutral element is `lift`.
0172     //!
0173     //!
0174     //! Refined concepts
0175     //! ----------------
0176     //! 1. `Functor`
0177     //! 2. `Applicative` (free implementation of `ap`)\n
0178     //! When the minimal complete definition for `Monad` and `Functor` are
0179     //! both satisfied, it is possible to implement `ap` by setting
0180     //! @code
0181     //!     ap(fs, xs) = chain(fs, [](auto f) {
0182     //!         return transform(xs, f);
0183     //!     })
0184     //! @endcode
0185     //!
0186     //!
0187     //! Concrete models
0188     //! ---------------
0189     //! `hana::lazy`, `hana::optional`, `hana::tuple`
0190     //!
0191     //!
0192     //! [1]: https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/
0193     //! [2]: https://wiki.haskell.org/Typeclassopedia#Monad
0194     template <typename M>
0195     struct Monad;
0196 }} // end namespace boost::hana
0197 
0198 #endif // !BOOST_HANA_FWD_CONCEPT_MONAD_HPP