foldable.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*!
  2. @file
  3. Forward declares `boost::hana::Foldable`.
  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_FOLDABLE_HPP
  9. #define BOOST_HANA_FWD_CONCEPT_FOLDABLE_HPP
  10. #include <boost/hana/config.hpp>
  11. namespace boost { namespace hana {
  12. //! @ingroup group-concepts
  13. //! @defgroup group-Foldable Foldable
  14. //! The `Foldable` concept represents data structures that can be reduced
  15. //! to a single value.
  16. //!
  17. //! Generally speaking, folding refers to the concept of summarizing a
  18. //! complex structure as a single value, by successively applying a
  19. //! binary operation which reduces two elements of the structure to a
  20. //! single value. Folds come in many flavors; left folds, right folds,
  21. //! folds with and without an initial reduction state, and their monadic
  22. //! variants. This concept is able to express all of these fold variants.
  23. //!
  24. //! Another way of seeing `Foldable` is as data structures supporting
  25. //! internal iteration with the ability to accumulate a result. By
  26. //! internal iteration, we mean that the _loop control_ is in the hand
  27. //! of the structure, not the caller. Hence, it is the structure who
  28. //! decides when the iteration stops, which is normally when the whole
  29. //! structure has been consumed. Since C++ is an eager language, this
  30. //! requires `Foldable` structures to be finite, or otherwise one would
  31. //! need to loop indefinitely to consume the whole structure.
  32. //!
  33. //! @note
  34. //! While the fact that `Foldable` only works for finite structures may
  35. //! seem overly restrictive in comparison to the Haskell definition of
  36. //! `Foldable`, a finer grained separation of the concepts should
  37. //! mitigate the issue. For iterating over possibly infinite data
  38. //! structures, see the `Iterable` concept. For searching a possibly
  39. //! infinite data structure, see the `Searchable` concept.
  40. //!
  41. //!
  42. //! Minimal complete definition
  43. //! ---------------------------
  44. //! `fold_left` or `unpack`
  45. //!
  46. //! However, please note that a minimal complete definition provided
  47. //! through `unpack` will be much more compile-time efficient than one
  48. //! provided through `fold_left`.
  49. //!
  50. //!
  51. //! Concrete models
  52. //! ---------------
  53. //! `hana::map`, `hana::optional`, `hana::pair`, `hana::set`,
  54. //! `hana::range`, `hana::tuple`
  55. //!
  56. //!
  57. //! @anchor Foldable-lin
  58. //! The linearization of a `Foldable`
  59. //! ---------------------------------
  60. //! Intuitively, for a `Foldable` structure `xs`, the _linearization_ of
  61. //! `xs` is the sequence of all the elements in `xs` as if they had been
  62. //! put in a list:
  63. //! @code
  64. //! linearization(xs) = [x1, x2, ..., xn]
  65. //! @endcode
  66. //!
  67. //! Note that it is always possible to produce such a linearization
  68. //! for a finite `Foldable` by setting
  69. //! @code
  70. //! linearization(xs) = fold_left(xs, [], flip(prepend))
  71. //! @endcode
  72. //! for an appropriate definition of `[]` and `prepend`. The notion of
  73. //! linearization is useful for expressing various properties of
  74. //! `Foldable` structures, and is used across the documentation. Also
  75. //! note that `Iterable`s define an [extended version](@ref Iterable-lin)
  76. //! of this allowing for infinite structures.
  77. //!
  78. //!
  79. //! Compile-time Foldables
  80. //! ----------------------
  81. //! A compile-time `Foldable` is a `Foldable` whose total length is known
  82. //! at compile-time. In other words, it is a `Foldable` whose `length`
  83. //! method returns a `Constant` of an unsigned integral type. When
  84. //! folding a compile-time `Foldable`, the folding can be unrolled,
  85. //! because the final number of steps of the algorithm is known at
  86. //! compile-time.
  87. //!
  88. //! Additionally, the `unpack` method is only available to compile-time
  89. //! `Foldable`s. This is because the return _type_ of `unpack` depends
  90. //! on the number of objects in the structure. Being able to resolve
  91. //! `unpack`'s return type at compile-time hence requires the length of
  92. //! the structure to be known at compile-time too.
  93. //!
  94. //! __In the current version of the library, only compile-time `Foldable`s
  95. //! are supported.__ While it would be possible in theory to support
  96. //! runtime `Foldable`s too, doing so efficiently requires more research.
  97. //!
  98. //!
  99. //! Provided conversion to `Sequence`s
  100. //! ----------------------------------
  101. //! Given a tag `S` which is a `Sequence`, an object whose tag is a model
  102. //! of the `Foldable` concept can be converted to an object of tag `S`.
  103. //! In other words, a `Foldable` can be converted to a `Sequence` `S`, by
  104. //! simply taking the linearization of the `Foldable` and creating the
  105. //! sequence with that. More specifically, given a `Foldable` `xs` with a
  106. //! linearization of `[x1, ..., xn]` and a `Sequence` tag `S`, `to<S>(xs)`
  107. //! is equivalent to `make<S>(x1, ..., xn)`.
  108. //! @include example/foldable/to.cpp
  109. //!
  110. //!
  111. //! Free model for builtin arrays
  112. //! -----------------------------
  113. //! Builtin arrays whose size is known can be folded as-if they were
  114. //! homogeneous tuples. However, note that builtin arrays can't be
  115. //! made more than `Foldable` (e.g. `Iterable`) because they can't
  116. //! be empty and they also can't be returned from functions.
  117. //!
  118. //!
  119. //! @anchor monadic-folds
  120. //! Primer on monadic folds
  121. //! -----------------------
  122. //! A monadic fold is a fold in which subsequent calls to the binary
  123. //! function are chained with the monadic `chain` operator of the
  124. //! corresponding Monad. This allows a structure to be folded in a
  125. //! custom monadic context. For example, performing a monadic fold with
  126. //! the `hana::optional` monad would require the binary function to return
  127. //! the result as a `hana::optional`, and the fold would abort and return
  128. //! `nothing` whenever one of the accumulation step would fail (i.e.
  129. //! return `nothing`). If, however, all the reduction steps succeed,
  130. //! then `just` the result would be returned. Different monads will of
  131. //! course result in different effects.
  132. template <typename T>
  133. struct Foldable;
  134. }} // end namespace boost::hana
  135. #endif // !BOOST_HANA_FWD_CONCEPT_FOLDABLE_HPP