/*! @file Defines `boost::hana::monadic_fold_right`. Copyright Louis Dionne 2013-2022 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_HANA_MONADIC_FOLD_RIGHT_HPP #define BOOST_HANA_MONADIC_FOLD_RIGHT_HPP #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace hana { //! @cond template template constexpr decltype(auto) monadic_fold_right_t::operator()(Xs&& xs, State&& state, F&& f) const { using S = typename hana::tag_of::type; using MonadicFoldRight = BOOST_HANA_DISPATCH_IF(monadic_fold_right_impl, hana::Foldable::value ); #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Monad::value, "hana::monadic_fold_right requires 'M' to be a Monad"); static_assert(hana::Foldable::value, "hana::monadic_fold_right(xs, state, f) requires 'xs' to be Foldable"); #endif return MonadicFoldRight::template apply(static_cast(xs), static_cast(state), static_cast(f)); } //! @endcond //! @cond template template constexpr decltype(auto) monadic_fold_right_t::operator()(Xs&& xs, F&& f) const { using S = typename hana::tag_of::type; using MonadicFoldRight = BOOST_HANA_DISPATCH_IF(monadic_fold_right_impl, hana::Foldable::value ); #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::Monad::value, "hana::monadic_fold_right requires 'M' to be a Monad"); static_assert(hana::Foldable::value, "hana::monadic_fold_right(xs, f) requires 'xs' to be Foldable"); #endif return MonadicFoldRight::template apply(static_cast(xs), static_cast(f)); } //! @endcond namespace detail { struct foldrM_helper { template constexpr decltype(auto) operator()(F&& f, K&& k, X&& x, Z&& z) const { return hana::chain( static_cast(f)( static_cast(x), static_cast(z) ), static_cast(k) ); } }; template struct monadic_foldr1_helper { F f; template constexpr decltype(auto) operator()(X&& x, Y&& y) const { return f(static_cast(x), static_cast(y)); } template constexpr decltype(auto) operator()(X&& x, End) const { return hana::lift(static_cast(x)); } }; } template struct monadic_fold_right_impl> : default_ { // with state template static constexpr decltype(auto) apply(Xs&& xs, S&& s, F&& f) { return hana::fold_left( static_cast(xs), hana::lift, hana::curry<3>(hana::partial( detail::foldrM_helper{}, static_cast(f) )) )(static_cast(s)); } // without state template static constexpr decltype(auto) apply(Xs&& xs, F&& f) { struct end { }; using G = detail::monadic_foldr1_helper::type>; decltype(auto) result = hana::monadic_fold_right( static_cast(xs), end{}, G{static_cast(f)} ); static_assert(!std::is_same< std::remove_reference_t, decltype(hana::lift(end{})) >{}, "hana::monadic_fold_right(xs, f) requires 'xs' to be non-empty"); return result; } }; }} // end namespace boost::hana #endif // !BOOST_HANA_MONADIC_FOLD_RIGHT_HPP