Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:04

0001 /*!
0002 @file
0003 Defines `boost::hana::monadic_fold_right`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0008  */
0009 
0010 #ifndef BOOST_HANA_MONADIC_FOLD_RIGHT_HPP
0011 #define BOOST_HANA_MONADIC_FOLD_RIGHT_HPP
0012 
0013 #include <boost/hana/fwd/monadic_fold_right.hpp>
0014 
0015 #include <boost/hana/chain.hpp>
0016 #include <boost/hana/concept/foldable.hpp>
0017 #include <boost/hana/concept/monad.hpp>
0018 #include <boost/hana/config.hpp>
0019 #include <boost/hana/core/dispatch.hpp>
0020 #include <boost/hana/detail/decay.hpp>
0021 #include <boost/hana/fold_left.hpp>
0022 #include <boost/hana/functional/curry.hpp>
0023 #include <boost/hana/functional/partial.hpp>
0024 #include <boost/hana/lift.hpp>
0025 
0026 #include <type_traits>
0027 
0028 
0029 namespace boost { namespace hana {
0030     //! @cond
0031     template <typename M>
0032     template <typename Xs, typename State, typename F>
0033     constexpr decltype(auto) monadic_fold_right_t<M>::operator()(Xs&& xs, State&& state, F&& f) const {
0034         using S = typename hana::tag_of<Xs>::type;
0035         using MonadicFoldRight = BOOST_HANA_DISPATCH_IF(monadic_fold_right_impl<S>,
0036             hana::Foldable<S>::value
0037         );
0038 
0039     #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
0040         static_assert(hana::Monad<M>::value,
0041         "hana::monadic_fold_right<M> requires 'M' to be a Monad");
0042 
0043         static_assert(hana::Foldable<S>::value,
0044         "hana::monadic_fold_right<M>(xs, state, f) requires 'xs' to be Foldable");
0045     #endif
0046 
0047         return MonadicFoldRight::template apply<M>(static_cast<Xs&&>(xs),
0048                                                    static_cast<State&&>(state),
0049                                                    static_cast<F&&>(f));
0050     }
0051     //! @endcond
0052 
0053     //! @cond
0054     template <typename M>
0055     template <typename Xs, typename F>
0056     constexpr decltype(auto) monadic_fold_right_t<M>::operator()(Xs&& xs, F&& f) const {
0057         using S = typename hana::tag_of<Xs>::type;
0058         using MonadicFoldRight = BOOST_HANA_DISPATCH_IF(monadic_fold_right_impl<S>,
0059             hana::Foldable<S>::value
0060         );
0061 
0062     #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
0063         static_assert(hana::Monad<M>::value,
0064         "hana::monadic_fold_right<M> requires 'M' to be a Monad");
0065 
0066         static_assert(hana::Foldable<S>::value,
0067         "hana::monadic_fold_right<M>(xs, f) requires 'xs' to be Foldable");
0068     #endif
0069         return MonadicFoldRight::template apply<M>(static_cast<Xs&&>(xs),
0070                                                    static_cast<F&&>(f));
0071     }
0072     //! @endcond
0073 
0074     namespace detail {
0075         struct foldrM_helper {
0076             template <typename F, typename K, typename X, typename Z>
0077             constexpr decltype(auto) operator()(F&& f, K&& k, X&& x, Z&& z) const {
0078                 return hana::chain(
0079                     static_cast<F&&>(f)(
0080                         static_cast<X&&>(x),
0081                         static_cast<Z&&>(z)
0082                     ),
0083                     static_cast<K&&>(k)
0084                 );
0085             }
0086         };
0087 
0088         template <typename End, typename M, typename F>
0089         struct monadic_foldr1_helper {
0090             F f;
0091             template <typename X, typename Y>
0092             constexpr decltype(auto) operator()(X&& x, Y&& y) const
0093             { return f(static_cast<X&&>(x), static_cast<Y&&>(y)); }
0094             template <typename X>
0095             constexpr decltype(auto) operator()(X&& x, End) const
0096             { return hana::lift<M>(static_cast<X&&>(x)); }
0097         };
0098     }
0099 
0100     template <typename T, bool condition>
0101     struct monadic_fold_right_impl<T, when<condition>> : default_ {
0102         // with state
0103         template <typename M, typename Xs, typename S, typename F>
0104         static constexpr decltype(auto) apply(Xs&& xs, S&& s, F&& f) {
0105             return hana::fold_left(
0106                 static_cast<Xs&&>(xs),
0107                 hana::lift<M>,
0108                 hana::curry<3>(hana::partial(
0109                     detail::foldrM_helper{}, static_cast<F&&>(f)
0110                 ))
0111             )(static_cast<S&&>(s));
0112         }
0113 
0114         // without state
0115         template <typename M, typename Xs, typename F>
0116         static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
0117             struct end { };
0118             using G = detail::monadic_foldr1_helper<end, M, typename detail::decay<F>::type>;
0119             decltype(auto) result = hana::monadic_fold_right<M>(
0120                 static_cast<Xs&&>(xs),
0121                 end{},
0122                 G{static_cast<F&&>(f)}
0123             );
0124 
0125             static_assert(!std::is_same<
0126                 std::remove_reference_t<decltype(result)>,
0127                 decltype(hana::lift<M>(end{}))
0128             >{},
0129             "hana::monadic_fold_right<M>(xs, f) requires 'xs' to be non-empty");
0130             return result;
0131         }
0132     };
0133 }} // end namespace boost::hana
0134 
0135 #endif // !BOOST_HANA_MONADIC_FOLD_RIGHT_HPP