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_left`.
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_LEFT_HPP
0011 #define BOOST_HANA_MONADIC_FOLD_LEFT_HPP
0012 
0013 #include <boost/hana/fwd/monadic_fold_left.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_right.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_left_t<M>::operator()(Xs&& xs, State&& state, F&& f) const {
0034         using S = typename hana::tag_of<Xs>::type;
0035         using MonadicFoldLeft = BOOST_HANA_DISPATCH_IF(monadic_fold_left_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_left<M> requires 'M' to be a Monad");
0042 
0043         static_assert(hana::Foldable<S>::value,
0044         "hana::monadic_fold_left<M>(xs, state, f) requires 'xs' to be Foldable");
0045     #endif
0046 
0047         return MonadicFoldLeft::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_left_t<M>::operator()(Xs&& xs, F&& f) const {
0057         using S = typename hana::tag_of<Xs>::type;
0058         using MonadicFoldLeft = BOOST_HANA_DISPATCH_IF(monadic_fold_left_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_left<M> requires 'M' to be a Monad");
0065 
0066         static_assert(hana::Foldable<S>::value,
0067         "hana::monadic_fold_left<M>(xs, f) requires 'xs' to be Foldable");
0068     #endif
0069 
0070         return MonadicFoldLeft::template apply<M>(static_cast<Xs&&>(xs),
0071                                                   static_cast<F&&>(f));
0072     }
0073     //! @endcond
0074 
0075     namespace detail {
0076         struct foldlM_helper {
0077             template <typename F, typename X, typename K, typename Z>
0078             constexpr decltype(auto) operator()(F&& f, X&& x, K&& k, Z&& z) const {
0079                 return hana::chain(
0080                     static_cast<F&&>(f)(
0081                         static_cast<Z&&>(z),
0082                         static_cast<X&&>(x)
0083                     ),
0084                     static_cast<K&&>(k)
0085                 );
0086             }
0087         };
0088 
0089         template <typename End, typename M, typename F>
0090         struct monadic_foldl1_helper {
0091             F f;
0092             template <typename X, typename Y>
0093             constexpr decltype(auto) operator()(X&& x, Y&& y) const
0094             { return f(static_cast<X&&>(x), static_cast<Y&&>(y)); }
0095             template <typename Y>
0096             constexpr decltype(auto) operator()(End, Y&& y) const
0097             { return hana::lift<M>(static_cast<Y&&>(y)); }
0098         };
0099     }
0100 
0101     template <typename T, bool condition>
0102     struct monadic_fold_left_impl<T, when<condition>> : default_ {
0103         // with state
0104         template <typename M, typename Xs, typename S, typename F>
0105         static constexpr decltype(auto) apply(Xs&& xs, S&& s, F&& f) {
0106             return hana::fold_right(
0107                 static_cast<Xs&&>(xs),
0108                 hana::lift<M>,
0109                 hana::curry<3>(hana::partial(
0110                     detail::foldlM_helper{}, static_cast<F&&>(f)
0111                 ))
0112             )(static_cast<S&&>(s));
0113         }
0114 
0115         // without state
0116         template <typename M, typename Xs, typename F>
0117         static constexpr decltype(auto) apply(Xs&& xs, F&& f) {
0118             struct end { };
0119             using G = detail::monadic_foldl1_helper<end, M, typename detail::decay<F>::type>;
0120             decltype(auto) result = hana::monadic_fold_left<M>(
0121                 static_cast<Xs&&>(xs),
0122                 end{},
0123                 G{static_cast<F&&>(f)}
0124             );
0125 
0126             static_assert(!std::is_same<
0127                 std::remove_reference_t<decltype(result)>,
0128                 decltype(hana::lift<M>(end{}))
0129             >{},
0130             "hana::monadic_fold_left<M>(xs, f) requires 'xs' to be non-empty");
0131             return result;
0132         }
0133     };
0134 }} // end namespace boost::hana
0135 
0136 #endif // !BOOST_HANA_MONADIC_FOLD_LEFT_HPP