| 1 | /*! |
| 2 | @file |
| 3 | Forward declares `boost::hana::Applicative`. |
| 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_APPLICATIVE_HPP |
| 11 | #define BOOST_HANA_FWD_CONCEPT_APPLICATIVE_HPP |
| 12 | |
| 13 | #include <boost/hana/config.hpp> |
| 14 | |
| 15 | |
| 16 | namespace boost { namespace hana { |
| 17 | //! @ingroup group-concepts |
| 18 | //! @defgroup group-Applicative Applicative |
| 19 | //! The `Applicative` concept represents `Functor`s with the ability |
| 20 | //! to lift values and combine computations. |
| 21 | //! |
| 22 | //! A `Functor` can only take a normal function and map it over a |
| 23 | //! structure containing values to obtain a new structure containing |
| 24 | //! values. Intuitively, an `Applicative` can also take a value and |
| 25 | //! lift it into the structure. In addition, an `Applicative` can take |
| 26 | //! a structure containing functions and apply it to a structure |
| 27 | //! containing values to obtain a new structure containing values. |
| 28 | //! By currying the function(s) inside the structure, it is then |
| 29 | //! also possible to apply n-ary functions to n structures containing |
| 30 | //! values. |
| 31 | //! |
| 32 | //! @note |
| 33 | //! This documentation does not go into much details about the nature |
| 34 | //! of applicatives. However, the [Typeclassopedia][1] is a nice |
| 35 | //! Haskell-oriented resource where such information can be found. |
| 36 | //! |
| 37 | //! |
| 38 | //! Minimal complete definition |
| 39 | //! --------------------------- |
| 40 | //! `lift` and `ap` satisfying the laws below. An `Applicative` must |
| 41 | //! also be a `Functor`. |
| 42 | //! |
| 43 | //! |
| 44 | //! Laws |
| 45 | //! ---- |
| 46 | //! Given an `Applicative` `F`, the following laws must be satisfied: |
| 47 | //! 1. Identity\n |
| 48 | //! For all objects `xs` of tag `F(A)`, |
| 49 | //! @code |
| 50 | //! ap(lift<F>(id), xs) == xs |
| 51 | //! @endcode |
| 52 | //! |
| 53 | //! 2. Composition\n |
| 54 | //! For all objects `xs` of tag `F(A)` and functions-in-an-applicative |
| 55 | //! @f$ fs : F(B \to C) @f$, |
| 56 | //! @f$ gs : F(A \to B) @f$, |
| 57 | //! @code |
| 58 | //! ap(ap(lift<F>(compose), fs, gs), xs) == ap(fs, ap(gs, xs)) |
| 59 | //! @endcode |
| 60 | //! |
| 61 | //! 3. Homomorphism\n |
| 62 | //! For all objects `x` of tag `A` and functions @f$ f : A \to B @f$, |
| 63 | //! @code |
| 64 | //! ap(lift<F>(f), lift<F>(x)) == lift<F>(f(x)) |
| 65 | //! @endcode |
| 66 | //! |
| 67 | //! 4. Interchange\n |
| 68 | //! For all objects `x` of tag `A` and functions-in-an-applicative |
| 69 | //! @f$ fs : F(A \to B) @f$, |
| 70 | //! @code |
| 71 | //! ap(fs, lift<F>(x)) == ap(lift<F>(apply(-, x)), fs) |
| 72 | //! @endcode |
| 73 | //! where `apply(-, x)` denotes the partial application of the `apply` |
| 74 | //! function from the @ref group-functional module to the `x` argument. |
| 75 | //! |
| 76 | //! As a consequence of these laws, the model of `Functor` for `F` will |
| 77 | //! satisfy the following for all objects `xs` of tag `F(A)` and functions |
| 78 | //! @f$ f : A \to B @f$: |
| 79 | //! @code |
| 80 | //! transform(xs, f) == ap(lift<F>(f), xs) |
| 81 | //! @endcode |
| 82 | //! |
| 83 | //! |
| 84 | //! Refined concept |
| 85 | //! --------------- |
| 86 | //! 1. `Functor` (free model)\n |
| 87 | //! As a consequence of the laws, any `Applicative F` can be made a |
| 88 | //! `Functor` by setting |
| 89 | //! @code |
| 90 | //! transform(xs, f) = ap(lift<F>(f), xs) |
| 91 | //! @endcode |
| 92 | //! |
| 93 | //! |
| 94 | //! Concrete models |
| 95 | //! --------------- |
| 96 | //! `hana::lazy`, `hana::optional`, `hana::tuple` |
| 97 | //! |
| 98 | //! |
| 99 | //! @anchor applicative-transformation |
| 100 | //! Structure-preserving functions |
| 101 | //! ------------------------------ |
| 102 | //! An _applicative transformation_ is a function @f$ t : F(X) \to G(X) @f$ |
| 103 | //! between two Applicatives `F` and `G`, where `X` can be any tag, and |
| 104 | //! which preserves the operations of an Applicative. In other words, for |
| 105 | //! all objects `x` of tag `X`, functions-in-an-applicative |
| 106 | //! @f$ fs : F(X \to Y) @f$ and objects `xs` of tag `F(X)`, |
| 107 | //! @code |
| 108 | //! t(lift<F>(x)) == lift<G>(x) |
| 109 | //! t(ap(fs, xs)) == ap(t(fs), t(xs)) |
| 110 | //! @endcode |
| 111 | //! |
| 112 | //! [1]: https://wiki.haskell.org/Typeclassopedia#Applicative |
| 113 | template <typename A> |
| 114 | struct Applicative; |
| 115 | }} // end namespace boost::hana |
| 116 | |
| 117 | #endif // !BOOST_HANA_FWD_CONCEPT_APPLICATIVE_HPP |
| 118 | |