1 /*! 2 @file 3 Forward declares `boost::hana::lazy`. 4 5 @copyright Louis Dionne 2013-2017 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_LAZY_HPP 11 #define BOOST_HANA_FWD_LAZY_HPP 12 13 #include <boost/hana/config.hpp> 14 #include <boost/hana/fwd/core/make.hpp> 15 16 17 BOOST_HANA_NAMESPACE_BEGIN 18 //! @ingroup group-datatypes 19 //! `hana::lazy` implements superficial laziness via a monadic interface. 20 //! 21 //! It is important to understand that the laziness implemented by `lazy` 22 //! is only superficial; only function applications made inside the `lazy` 23 //! monad can be made lazy, not all their subexpressions. 24 //! 25 //! 26 //! @note 27 //! The actual representation of `hana::lazy` is completely 28 //! implementation-defined. Lazy values may only be created through 29 //! `hana::make_lazy`, and they can be stored in variables using 30 //! `auto`, but any other assumption about the representation of 31 //! `hana::lazy<...>` should be avoided. In particular, one should 32 //! not rely on the fact that `hana::lazy<...>` can be pattern-matched 33 //! on, because it may be a dependent type. 34 //! 35 //! 36 //! Modeled concepts 37 //! ---------------- 38 //! 1. `Functor`\n 39 //! Applying a function over a lazy value with `transform` returns the 40 //! result of applying the function, as a lazy value. 41 //! @include example/lazy/functor.cpp 42 //! 43 //! 2. `Applicative`\n 44 //! A normal value can be lifted into a lazy value by using `lift<lazy_tag>`. 45 //! A lazy function can be lazily applied to a lazy value by using `ap`. 46 //! 47 //! 3. `Monad`\n 48 //! The `lazy` monad allows combining lazy computations into larger 49 //! lazy computations. Note that the `|` operator can be used in place 50 //! of the `chain` function. 51 //! @include example/lazy/monad.cpp 52 //! 53 //! 4. `Comonad`\n 54 //! The `lazy` comonad allows evaluating a lazy computation to get its 55 //! result and lazily applying functions taking lazy inputs to lazy 56 //! values. This [blog post][1] goes into more details about lazy 57 //! evaluation and comonads. 58 //! @include example/lazy/comonad.cpp 59 //! 60 //! 61 //! @note 62 //! `hana::lazy` only models a few concepts because providing more 63 //! functionality would require evaluating the lazy values in most cases. 64 //! Since this raises some issues such as side effects and memoization, 65 //! the interface is kept minimal. 66 //! 67 //! 68 //! [1]: http://ldionne.com/2015/03/16/laziness-as-a-comonad 69 #ifdef BOOST_HANA_DOXYGEN_INVOKED 70 template <typename implementation_defined> 71 struct lazy { 72 //! Equivalent to `hana::chain`. 73 template <typename ...T, typename F> 74 friend constexpr auto operator|(lazy<T...>, F); 75 }; 76 #else 77 // We do not _actually_ define the lazy<...> type. Per the documentation, 78 // users can't rely on it being anything, and so they should never use 79 // it explicitly. The implementation in <boost/hana/lazy.hpp> is much 80 // simpler if we use different types for lazy calls and lazy values. 81 #endif 82 83 //! Tag representing `hana::lazy`. 84 //! @relates hana::lazy 85 struct lazy_tag { }; 86 87 //! Lifts a normal value to a lazy one. 88 //! @relates hana::lazy 89 //! 90 //! `make<lazy_tag>` can be used to lift a normal value or a function call 91 //! into a lazy expression. Precisely, `make<lazy_tag>(x)` is a lazy value 92 //! equal to `x`, and `make<lazy_tag>(f)(x1, ..., xN)` is a lazy function 93 //! call that is equal to `f(x1, ..., xN)` when it is `eval`uated. 94 //! 95 //! @note 96 //! It is interesting to note that `make<lazy_tag>(f)(x1, ..., xN)` is 97 //! equivalent to 98 //! @code 99 //! ap(make<lazy_tag>(f), lift<lazy_tag>(x1), ..., lift<lazy_tag>(xN)) 100 //! @endcode 101 //! which in turn is equivalent to `make<lazy_tag>(f(x1, ..., xN))`, except 102 //! for the fact that the inner call to `f` is evaluated lazily. 103 //! 104 //! 105 //! Example 106 //! ------- 107 //! @include example/lazy/make.cpp 108 #ifdef BOOST_HANA_DOXYGEN_INVOKED 109 template <> __anon19dc747c0102(auto&& x) 110 constexpr auto make<lazy_tag> = [](auto&& x) { 111 return lazy<implementation_defined>{forwarded(x)}; 112 }; 113 #endif 114 115 //! Alias to `make<lazy_tag>`; provided for convenience. 116 //! @relates hana::lazy 117 //! 118 //! Example 119 //! ------- 120 //! @include example/lazy/make.cpp 121 constexpr auto make_lazy = make<lazy_tag>; 122 BOOST_HANA_NAMESPACE_END 123 124 #endif // !BOOST_HANA_FWD_LAZY_HPP 125