functor.hpp 6.0 KB

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