| 1 | /*! |
| 2 | @file |
| 3 | Forward declares `boost::hana::Functor`. |
| 4 | |
| 5 | Copyright Louis Dionne 2013-2022 |
| 6 | Distributed under the Boost Software License, Version 1.0. |
| 7 | (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) |
| 8 | */ |
| 9 | |
| 10 | #ifndef BOOST_HANA_FWD_CONCEPT_FUNCTOR_HPP |
| 11 | #define BOOST_HANA_FWD_CONCEPT_FUNCTOR_HPP |
| 12 | |
| 13 | #include <boost/hana/config.hpp> |
| 14 | |
| 15 | |
| 16 | namespace boost { namespace hana { |
| 17 | //! @ingroup group-concepts |
| 18 | //! @defgroup group-Functor Functor |
| 19 | //! The `Functor` concept represents types that can be mapped over. |
| 20 | //! |
| 21 | //! Intuitively, a [Functor][1] is some kind of box that can hold generic |
| 22 | //! data and map a function over this data to create a new, transformed |
| 23 | //! box. Because we are only interested in mapping a function over the |
| 24 | //! contents of a black box, the only real requirement for being a functor |
| 25 | //! is to provide a function which can do the mapping, along with a couple |
| 26 | //! of guarantees that the mapping is well-behaved. Those requirements are |
| 27 | //! made precise in the laws below. The pattern captured by `Functor` is |
| 28 | //! very general, which makes it widely useful. A lot of objects can be |
| 29 | //! made `Functor`s in one way or another, the most obvious example being |
| 30 | //! sequences with the usual mapping of the function on each element. |
| 31 | //! While this documentation will not go into much more details about |
| 32 | //! the nature of functors, the [Typeclassopedia][2] is a nice |
| 33 | //! Haskell-oriented resource for such information. |
| 34 | //! |
| 35 | //! Functors are parametric data types which are parameterized over the |
| 36 | //! data type of the objects they contain. Like everywhere else in Hana, |
| 37 | //! this parametricity is only at the documentation level and it is not |
| 38 | //! enforced. |
| 39 | //! |
| 40 | //! In this library, the mapping function is called `transform` after the |
| 41 | //! `std::transform` algorithm, but other programming languages have given |
| 42 | //! it different names (usually `map`). |
| 43 | //! |
| 44 | //! @note |
| 45 | //! The word _functor_ comes from functional programming, where the |
| 46 | //! concept has been used for a while, notably in the Haskell programming |
| 47 | //! language. Haskell people borrowed the term from [category theory][3], |
| 48 | //! which, broadly speaking, is a field of mathematics dealing with |
| 49 | //! abstract structures and transformations between those structures. |
| 50 | //! |
| 51 | //! |
| 52 | //! Minimal complete definitions |
| 53 | //! ---------------------------- |
| 54 | //! 1. `transform`\n |
| 55 | //! When `transform` is specified, `adjust_if` is defined analogously to |
| 56 | //! @code |
| 57 | //! adjust_if(xs, pred, f) = transform(xs, [](x){ |
| 58 | //! if pred(x) then f(x) else x |
| 59 | //! }) |
| 60 | //! @endcode |
| 61 | //! |
| 62 | //! 2. `adjust_if`\n |
| 63 | //! When `adjust_if` is specified, `transform` is defined analogously to |
| 64 | //! @code |
| 65 | //! transform(xs, f) = adjust_if(xs, always(true), f) |
| 66 | //! @endcode |
| 67 | //! |
| 68 | //! |
| 69 | //! Laws |
| 70 | //! ---- |
| 71 | //! Let `xs` be a Functor with tag `F(A)`, |
| 72 | //! \f$ f : A \to B \f$ and |
| 73 | //! \f$ g : B \to C \f$. |
| 74 | //! The following laws must be satisfied: |
| 75 | //! @code |
| 76 | //! transform(xs, id) == xs |
| 77 | //! transform(xs, compose(g, f)) == transform(transform(xs, f), g) |
| 78 | //! @endcode |
| 79 | //! The first line says that mapping the identity function should not do |
| 80 | //! anything, which precludes the functor from doing something nasty |
| 81 | //! behind the scenes. The second line states that mapping the composition |
| 82 | //! of two functions is the same as mapping the first function, and then |
| 83 | //! the second on the result. While the usual functor laws are usually |
| 84 | //! restricted to the above, this library includes other convenience |
| 85 | //! methods and they should satisfy the following equations. |
| 86 | //! Let `xs` be a Functor with tag `F(A)`, |
| 87 | //! \f$ f : A \to A \f$, |
| 88 | //! \f$ \mathrm{pred} : A \to \mathrm{Bool} \f$ |
| 89 | //! for some `Logical` `Bool`, and `oldval`, `newval`, `value` objects |
| 90 | //! of tag `A`. Then, |
| 91 | //! @code |
| 92 | //! adjust(xs, value, f) == adjust_if(xs, equal.to(value), f) |
| 93 | //! adjust_if(xs, pred, f) == transform(xs, [](x){ |
| 94 | //! if pred(x) then f(x) else x |
| 95 | //! }) |
| 96 | //! replace_if(xs, pred, value) == adjust_if(xs, pred, always(value)) |
| 97 | //! replace(xs, oldval, newval) == replace_if(xs, equal.to(oldval), newval) |
| 98 | //! fill(xs, value) == replace_if(xs, always(true), value) |
| 99 | //! @endcode |
| 100 | //! The default definition of the methods will satisfy these equations. |
| 101 | //! |
| 102 | //! |
| 103 | //! Concrete models |
| 104 | //! --------------- |
| 105 | //! `hana::lazy`, `hana::optional`, `hana::tuple` |
| 106 | //! |
| 107 | //! |
| 108 | //! Structure-preserving functions for Functors |
| 109 | //! ------------------------------------------- |
| 110 | //! A mapping between two functors which also preserves the functor |
| 111 | //! laws is called a natural transformation (the term comes from |
| 112 | //! category theory). A natural transformation is a function `f` |
| 113 | //! from a functor `F` to a functor `G` such that for every other |
| 114 | //! function `g` with an appropriate signature and for every object |
| 115 | //! `xs` of tag `F(X)`, |
| 116 | //! @code |
| 117 | //! f(transform(xs, g)) == transform(f(xs), g) |
| 118 | //! @endcode |
| 119 | //! |
| 120 | //! There are several examples of such transformations, like `to<tuple_tag>` |
| 121 | //! when applied to an optional value. Indeed, for any function `g` and |
| 122 | //! `hana::optional` `opt`, |
| 123 | //! @code |
| 124 | //! to<tuple_tag>(transform(opt, g)) == transform(to<tuple_tag>(opt), g) |
| 125 | //! @endcode |
| 126 | //! |
| 127 | //! Of course, natural transformations are not limited to the `to<...>` |
| 128 | //! functions. However, note that any conversion function between Functors |
| 129 | //! should be natural for the behavior of the conversion to be intuitive. |
| 130 | //! |
| 131 | //! |
| 132 | //! [1]: http://en.wikipedia.org/wiki/Functor |
| 133 | //! [2]: https://wiki.haskell.org/Typeclassopedia#Functor |
| 134 | //! [3]: http://en.wikipedia.org/wiki/Category_theory |
| 135 | template <typename F> |
| 136 | struct Functor; |
| 137 | }} // end namespace boost::hana |
| 138 | |
| 139 | #endif // !BOOST_HANA_FWD_CONCEPT_FUNCTOR_HPP |
| 140 | |