summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/hana/test/_include/laws
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/hana/test/_include/laws
parentInitial commit. (diff)
downloadceph-upstream.tar.xz
ceph-upstream.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/hana/test/_include/laws')
-rw-r--r--src/boost/libs/hana/test/_include/laws/applicative.hpp196
-rw-r--r--src/boost/libs/hana/test/_include/laws/base.hpp369
-rw-r--r--src/boost/libs/hana/test/_include/laws/comonad.hpp53
-rw-r--r--src/boost/libs/hana/test/_include/laws/comparable.hpp167
-rw-r--r--src/boost/libs/hana/test/_include/laws/constant.hpp106
-rw-r--r--src/boost/libs/hana/test/_include/laws/euclidean_ring.hpp99
-rw-r--r--src/boost/libs/hana/test/_include/laws/foldable.hpp1104
-rw-r--r--src/boost/libs/hana/test/_include/laws/functor.hpp250
-rw-r--r--src/boost/libs/hana/test/_include/laws/group.hpp93
-rw-r--r--src/boost/libs/hana/test/_include/laws/hashable.hpp60
-rw-r--r--src/boost/libs/hana/test/_include/laws/iterable.hpp195
-rw-r--r--src/boost/libs/hana/test/_include/laws/logical.hpp137
-rw-r--r--src/boost/libs/hana/test/_include/laws/monad.hpp222
-rw-r--r--src/boost/libs/hana/test/_include/laws/monad_plus.hpp616
-rw-r--r--src/boost/libs/hana/test/_include/laws/monoid.hpp86
-rw-r--r--src/boost/libs/hana/test/_include/laws/orderable.hpp182
-rw-r--r--src/boost/libs/hana/test/_include/laws/product.hpp46
-rw-r--r--src/boost/libs/hana/test/_include/laws/ring.hpp125
-rw-r--r--src/boost/libs/hana/test/_include/laws/searchable.hpp611
-rw-r--r--src/boost/libs/hana/test/_include/laws/sequence.hpp133
-rw-r--r--src/boost/libs/hana/test/_include/laws/templates/seq.hpp132
21 files changed, 4982 insertions, 0 deletions
diff --git a/src/boost/libs/hana/test/_include/laws/applicative.hpp b/src/boost/libs/hana/test/_include/laws/applicative.hpp
new file mode 100644
index 000000000..a7de47b9d
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/applicative.hpp
@@ -0,0 +1,196 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_APPLICATIVE_HPP
+#define BOOST_HANA_TEST_LAWS_APPLICATIVE_HPP
+
+#include <boost/hana/ap.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/applicative.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/curry.hpp>
+#include <boost/hana/functional/id.hpp>
+#include <boost/hana/functional/placeholder.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/take_front.hpp>
+#include <boost/hana/transform.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename F, typename = when<true>>
+ struct TestApplicative : TestApplicative<F, laws> {
+ using TestApplicative<F, laws>::TestApplicative;
+ };
+
+ template <typename F>
+ struct TestApplicative<F, laws> {
+ template <typename Applicatives>
+ TestApplicative(Applicatives applicatives) {
+ hana::for_each(applicatives, [](auto a) {
+ static_assert(Applicative<decltype(a)>{}, "");
+ });
+
+ auto functions1 = hana::take_front(
+ hana::transform(applicatives, [](auto xs) {
+ return hana::transform(xs, hana::curry<2>(test::_injection<0>{}));
+ }), hana::int_c<3>);
+
+ auto functions2 = hana::take_front(
+ hana::transform(applicatives, [](auto xs) {
+ return hana::transform(xs, hana::curry<2>(test::_injection<1>{}));
+ }), hana::int_c<3>);
+
+ // identity
+ {
+ hana::for_each(applicatives, [](auto xs) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::ap(hana::lift<F>(hana::id), xs),
+ xs
+ ));
+ });
+ }
+
+ // composition
+ {
+ hana::for_each(applicatives, hana::capture(functions1, functions2)(
+ [](auto functions1, auto functions2, auto xs) {
+ hana::for_each(functions1, hana::capture(functions2, xs)(
+ [](auto functions2, auto xs, auto fs) {
+ hana::for_each(functions2, hana::capture(xs, fs)(
+ [](auto xs, auto fs, auto gs) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::ap(hana::ap(hana::lift<F>(compose), fs, gs), xs),
+ hana::ap(fs, hana::ap(gs, xs))
+ ));
+ }));}));}));
+ }
+
+ // homomorphism
+ {
+ test::_injection<0> f{};
+ test::ct_eq<3> x{};
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(hana::lift<F>(f), hana::lift<F>(x)),
+ hana::lift<F>(f(x))
+ ));
+ }
+
+ // interchange
+ {
+ hana::for_each(functions1, [](auto fs) {
+ test::ct_eq<4> x{};
+ BOOST_HANA_CHECK(hana::equal(
+ hana::ap(fs, hana::lift<F>(x)),
+ hana::ap(hana::lift<F>(hana::_(x)), fs)
+ ));
+ });
+ }
+
+ // definition of transform
+ {
+ hana::for_each(applicatives, [](auto xs) {
+ test::_injection<0> f{};
+ BOOST_HANA_CHECK(hana::equal(
+ hana::transform(xs, f),
+ hana::ap(hana::lift<F>(f), xs)
+ ));
+ });
+ }
+ }
+ };
+
+ template <typename S>
+ struct TestApplicative<S, when<Sequence<S>::value>>
+ : TestApplicative<S, laws>
+ {
+ template <typename Applicatives>
+ TestApplicative(Applicatives applicatives)
+ : TestApplicative<S, laws>{applicatives}
+ {
+ _injection<0> f{};
+ _injection<1> g{};
+ using test::ct_eq;
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // ap
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(), list()),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(), list(ct_eq<0>{})),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(), list(ct_eq<0>{}, ct_eq<1>{})),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(), list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f), list()),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f), list(ct_eq<0>{})),
+ list(f(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f), list(ct_eq<0>{}, ct_eq<1>{})),
+ list(f(ct_eq<0>{}), f(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f), list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ list(f(ct_eq<0>{}), f(ct_eq<1>{}), f(ct_eq<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f, g), list()),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f, g), list(ct_eq<0>{})),
+ list(f(ct_eq<0>{}), g(ct_eq<0>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f, g), list(ct_eq<0>{}, ct_eq<1>{})),
+ list(f(ct_eq<0>{}), f(ct_eq<1>{}), g(ct_eq<0>{}), g(ct_eq<1>{}))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::ap(list(f, g), list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})),
+ list(f(ct_eq<0>{}), f(ct_eq<1>{}), f(ct_eq<2>{}),
+ g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{}))
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // lift
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ lift<S>(ct_eq<0>{}),
+ list(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ lift<S>(ct_eq<1>{}),
+ list(ct_eq<1>{})
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_APPLICATIVE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/base.hpp b/src/boost/libs/hana/test/_include/laws/base.hpp
new file mode 100644
index 000000000..0f421b8ae
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/base.hpp
@@ -0,0 +1,369 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_BASE_HPP
+#define BOOST_HANA_TEST_LAWS_BASE_HPP
+
+#include <boost/hana/and.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/detail/wrong.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/eval_if.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/infix.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/fwd/concept/integral_constant.hpp>
+#include <boost/hana/fwd/core/to.hpp>
+#include <boost/hana/fwd/less.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/or.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <support/tracked.hpp>
+
+#include <type_traits>
+#include <utility>
+
+
+namespace boost { namespace hana {
+ //////////////////////////////////////////////////////////////////////////
+ // Misc
+ //////////////////////////////////////////////////////////////////////////
+ namespace test {
+ struct laws;
+
+ template <int i>
+ struct for_each_n_t {
+ static_assert(i > 0, "can't use for_each_n with i < 0");
+
+ template <typename Xs, typename F>
+ constexpr auto operator()(Xs const& xs, F const& f) const {
+ hana::for_each(xs,
+ hana::compose(
+ hana::partial(for_each_n_t<i - 1>{}, xs),
+ hana::partial(hana::partial, f)
+ )
+ );
+ }
+ };
+
+ template <>
+ struct for_each_n_t<1> {
+ template <typename Xs, typename F>
+ constexpr auto operator()(Xs const& xs, F const& f) const {
+ hana::for_each(xs, f);
+ }
+ };
+
+ template <int i>
+ constexpr for_each_n_t<i> for_each_n{};
+
+ auto foreach = hana::for_each;
+ constexpr auto foreach3 = for_each_n<3>;
+ constexpr auto foreach2 = for_each_n<2>;
+
+ struct implies_t {
+ template <typename P, typename Q>
+ constexpr decltype(auto) operator()(P&& p, Q&& q) const {
+ return hana::or_(hana::not_(static_cast<P&&>(p)),
+ static_cast<Q&&>(q));
+ }
+ };
+ constexpr auto implies = hana::infix(implies_t{});
+
+ struct iff_t {
+ template <typename P, typename Q>
+ constexpr decltype(auto) operator()(P&& p, Q&& q) const {
+ return hana::and_(implies(p, q), implies(q, p));
+ }
+ };
+ constexpr auto iff = hana::infix(iff_t{});
+
+ template <typename Cond, typename F>
+ constexpr decltype(auto) only_when_(Cond cond, F f) {
+ return hana::eval_if(cond, f, [](auto){ });
+ }
+
+ // A type with a constructor that must not be instantiated.
+ // This is to make sure we don't instantiate something else than
+ // the copy-constructor of the elements inside a container when we
+ // copy the container.
+ struct trap_construct {
+ trap_construct() = default;
+ trap_construct(trap_construct const&) = default;
+#ifndef BOOST_HANA_WORKAROUND_MSVC_MULTIPLECTOR_106654
+ trap_construct(trap_construct&) = default;
+#endif
+ trap_construct(trap_construct&&) = default;
+
+ template <typename X>
+ trap_construct(X&&) {
+ static_assert(detail::wrong<X>{},
+ "this constructor must not be instantiated");
+ }
+ };
+
+ // A move-only type. Useful for testing containers.
+ struct move_only {
+ move_only() = default;
+ move_only(move_only const&) = delete;
+ move_only(move_only&&) = default;
+ };
+
+ //////////////////////////////////////////////////////////////////////
+ // InjectionResult
+ //////////////////////////////////////////////////////////////////////
+ struct InjectionResult { };
+
+ template <int i, typename ...X>
+ struct injection_result {
+ using hana_tag = InjectionResult;
+ static constexpr int injection_id = i;
+ hana::tuple<X...> args;
+ Tracked tracker;
+
+ template <typename ...Y, typename = decltype(tuple<X...>{std::declval<Y>()...})>
+ constexpr explicit injection_result(Y&& ...y)
+ : args{static_cast<Y&&>(y)...}, tracker{i}
+ { }
+ };
+
+ //! A monotonic injective function.
+ //!
+ //! This is used in the unit tests, where we often just need a function
+ //! which preserves equality and order, but which also satisfies the
+ //! following law for all `Injection`s `f` and `g`:
+ //! @code
+ //! f(x) == g(x) if and only if f === g
+ //! @endcode
+ //! where `===` means _was created by the same call to `injection`_.
+ //! This allows creating several such functions in the unit tests while
+ //! conserving precious information such as the fact that
+ //! `f(g(x)) != g(f(x))`.
+ template <int i>
+ struct _injection {
+ template <typename ...X>
+ constexpr auto operator()(X&& ...x) const {
+ return injection_result<i,
+ typename std::decay<X>::type...
+ >{static_cast<X&&>(x)...};
+ }
+ };
+ } // end namespace test
+
+ template <>
+ struct equal_impl<test::InjectionResult, test::InjectionResult> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y) {
+ return hana::and_(
+ hana::bool_c<X::injection_id == Y::injection_id>,
+ hana::equal(x.args, y.args)
+ );
+ }
+ };
+
+ template <>
+ struct less_impl<test::InjectionResult, test::InjectionResult> {
+ template <typename X, typename Y>
+ static constexpr auto apply(X x, Y y) {
+ static_assert(X::injection_id == Y::injection_id,
+ "can't order the result of two different injections");
+ return hana::less(x.args, y.args);
+ }
+ };
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Integer
+ //////////////////////////////////////////////////////////////////////////
+ namespace test {
+ enum class Policy : int {
+ // One of those is mandatory
+ Constant = 1 << 0
+ , Constexpr = 1 << 1
+ , Runtime = 1 << 2
+
+ // Those are optional
+ , Tracked = 1 << 3
+ , Comparable = 1 << 4
+ , Orderable = 1 << 5
+ };
+
+ constexpr bool operator&&(Policy a, Policy b) {
+ return static_cast<int>(a) && static_cast<int>(b);
+ }
+
+ constexpr bool operator&&(Policy a, bool b) {
+ return static_cast<int>(a) && b;
+ }
+
+ constexpr bool operator&&(bool a, Policy b) {
+ return a && static_cast<int>(b);
+ }
+
+ constexpr bool operator||(Policy a, Policy b) {
+ return static_cast<int>(a) || static_cast<int>(b);
+ }
+
+ constexpr bool operator||(Policy a, bool b) {
+ return static_cast<int>(a) || b;
+ }
+
+ constexpr bool operator||(bool a, Policy b) {
+ return a || static_cast<int>(b);
+ }
+
+ constexpr bool operator!(Policy a) {
+ return !static_cast<int>(a);
+ }
+
+ constexpr Policy operator|(Policy a, Policy b) {
+ return static_cast<Policy>(static_cast<int>(a) | static_cast<int>(b));
+ }
+
+ constexpr Policy operator&(Policy a, Policy b) {
+ return static_cast<Policy>(static_cast<int>(a) & static_cast<int>(b));
+ }
+
+ template <Policy policy, typename = void>
+ struct Integer { };
+
+ template <Policy policy>
+ struct Integer<policy, std::enable_if_t<!!(policy & Policy::Constant)>> {
+ using value_type = int;
+ };
+
+ template <int i, Policy policy, typename = void>
+ struct integer {
+ static_assert(
+ !!(policy & (Policy::Constant | Policy::Constexpr | Policy::Runtime))
+ , "You must choose at least one of Constant, Constexpr and Runtime.");
+
+ static constexpr int value = i;
+ constexpr operator int() const { return value; }
+ using hana_tag = Integer<policy>;
+ Tracked tracker{i};
+ };
+
+ template <int i, Policy policy>
+ struct integer <i, policy, std::enable_if_t<!!(policy & Policy::Constexpr)>> {
+ static constexpr int value = i;
+ constexpr operator int() const { return value; }
+ using hana_tag = Integer<policy>;
+ };
+
+ template <int i>
+ struct eq : integer<i, Policy::Comparable | Policy::Runtime> { };
+
+ template <int i>
+ struct ct_eq : integer<i, Policy::Comparable | Policy::Constant> { };
+
+ template <int i>
+ struct cx_eq : integer<i, Policy::Comparable | Policy::Constexpr> { };
+
+ template <int i>
+ struct ord : integer<i, Policy::Orderable | Policy::Runtime> { };
+
+ template <int i>
+ struct ct_ord : integer<i, Policy::Orderable | Policy::Constant> { };
+
+ template <int i>
+ struct cx_ord : integer<i, Policy::Orderable | Policy::Constexpr> { };
+
+ template <int i>
+ struct _constant
+ : integer<i, Policy::Constant | Policy::Comparable | Policy::Orderable>
+ { };
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model of Constant/IntegralConstant
+ //////////////////////////////////////////////////////////////////////////
+ template <test::Policy policy>
+ struct IntegralConstant<test::Integer<policy>> {
+ static constexpr bool value = static_cast<bool>(policy & test::Policy::Constant);
+ };
+
+ template <test::Policy policy, typename C>
+ struct to_impl<test::Integer<policy>, C, when<
+ (policy & test::Policy::Constant) &&
+ hana::IntegralConstant<C>::value
+ >>
+ : embedding<is_embedded<typename C::value_type, int>::value>
+ {
+ template <typename N>
+ static constexpr auto apply(N const&) {
+ return test::integer<N::value, policy>{};
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model of Comparable
+ //////////////////////////////////////////////////////////////////////////
+ template <test::Policy p1, test::Policy p2>
+ struct equal_impl<test::Integer<p1>, test::Integer<p2>, when<
+ // both Comparable or Orderable
+ (p1 & (test::Policy::Comparable | test::Policy::Orderable)) &&
+ (p2 & (test::Policy::Comparable | test::Policy::Orderable)) &&
+
+ // one Constexpr and the other Constant, or both Constexpr
+ (((p1 & test::Policy::Constant) && (p2 & test::Policy::Constexpr)) ||
+ ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constant)) ||
+ ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constexpr)))
+ >> {
+ template <typename X, typename Y>
+ static constexpr bool apply(X const&, Y const&)
+ { return X::value == Y::value; }
+ };
+
+ template <test::Policy p1, test::Policy p2>
+ struct equal_impl<test::Integer<p1>, test::Integer<p2>, when<
+ // both Comparable or Orderable
+ (p1 & (test::Policy::Comparable | test::Policy::Orderable)) &&
+ (p2 & (test::Policy::Comparable | test::Policy::Orderable)) &&
+
+ // either one is Runtime
+ ((p1 & test::Policy::Runtime) || (p2 & test::Policy::Runtime))
+ >> {
+ template <typename X, typename Y>
+ static bool apply(X const&, Y const&)
+ { return X::value == Y::value; }
+ };
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Model of Orderable
+ //////////////////////////////////////////////////////////////////////////
+ template <test::Policy p1, test::Policy p2>
+ struct less_impl<test::Integer<p1>, test::Integer<p2>, when<
+ // both Orderable
+ (p1 & test::Policy::Orderable) && (p2 & test::Policy::Orderable) &&
+
+ // one Constexpr and the other Constant, or both Constexpr
+ (((p1 & test::Policy::Constant) && (p2 & test::Policy::Constexpr)) ||
+ ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constant)) ||
+ ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constexpr)))
+ >> {
+ template <typename X, typename Y>
+ static constexpr bool apply(X const&, Y const&)
+ { return X::value < Y::value; }
+ };
+
+ template <test::Policy p1, test::Policy p2>
+ struct less_impl<test::Integer<p1>, test::Integer<p2>, when<
+ // both Orderable
+ (p1 & test::Policy::Orderable) && (p2 & test::Policy::Orderable) &&
+
+ // either one is Runtime
+ ((p1 & test::Policy::Runtime) || (p2 & test::Policy::Runtime))
+ >> {
+ template <typename X, typename Y>
+ static bool apply(X const&, Y const&)
+ { return X::value < Y::value; }
+ };
+}} // end namespace boost::hana
+
+#endif // !BOOST_HANA_TEST_LAWS_BASE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/comonad.hpp b/src/boost/libs/hana/test/_include/laws/comonad.hpp
new file mode 100644
index 000000000..82ef7b32d
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/comonad.hpp
@@ -0,0 +1,53 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_COMONAD_HPP
+#define BOOST_HANA_TEST_LAWS_COMONAD_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/concept/comonad.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/functor.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename W, typename = when<true>>
+ struct TestComonad : TestComonad<W, laws> {
+ using TestComonad<W, laws>::TestComonad;
+ };
+
+ template <typename W>
+ struct TestComonad<W, laws> {
+ template <typename Ws>
+ TestComonad(Ws ws) {
+ hana::for_each(ws, [](auto w) {
+ static_assert(Comonad<decltype(w)>{}, "");
+
+ // extract(duplicate(w)) == w
+ BOOST_HANA_CHECK(hana::equal(
+ hana::extract(hana::duplicate(w)),
+ w
+ ));
+
+ // transform(duplicate(w), extract) == w
+ BOOST_HANA_CHECK(hana::equal(
+ hana::transform(hana::duplicate(w), extract),
+ w
+ ));
+
+ // duplicate(duplicate(w)) == transform(duplicate(w), duplicate)
+ BOOST_HANA_CHECK(hana::equal(
+ hana::duplicate(hana::duplicate(w)),
+ hana::transform(hana::duplicate(w), duplicate)
+ ));
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_COMONAD_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/comparable.hpp b/src/boost/libs/hana/test/_include/laws/comparable.hpp
new file mode 100644
index 000000000..24ce317b8
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/comparable.hpp
@@ -0,0 +1,167 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_COMPARABLE_HPP
+#define BOOST_HANA_TEST_LAWS_COMPARABLE_HPP
+
+#include <boost/hana/and.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/comparing.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/value.hpp>
+
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename T, typename = hana::when<true>>
+ struct TestComparable : TestComparable<T, laws> {
+ using TestComparable<T, laws>::TestComparable;
+ };
+
+ template <typename T>
+ struct TestComparable<T, laws> {
+ template <typename Xs>
+ TestComparable(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(hana::Comparable<decltype(x)>{}, "");
+ });
+
+ foreach2(xs, [](auto a, auto b) {
+
+ // reflexivity
+ BOOST_HANA_CHECK(
+ hana::equal(a, a)
+ );
+
+ // symmetry
+ BOOST_HANA_CHECK(
+ hana::equal(a, b) ^implies^ hana::equal(b, a)
+ );
+
+ // `not_equal` is the negation of `equal`
+ BOOST_HANA_CHECK(
+ hana::not_equal(a, b) ^iff^ hana::not_(hana::equal(a, b))
+ );
+
+ // equal.to and not_equal.to
+ BOOST_HANA_CHECK(
+ hana::equal.to(a)(b) ^iff^ hana::equal(a, b)
+ );
+
+ BOOST_HANA_CHECK(
+ hana::not_equal.to(a)(b) ^iff^ hana::not_equal(a, b)
+ );
+
+ // comparing
+ _injection<0> f{};
+ BOOST_HANA_CHECK(
+ hana::comparing(f)(a, b) ^iff^ hana::equal(f(a), f(b))
+ );
+ });
+
+ // transitivity
+ foreach3(xs, [](auto a, auto b, auto c) {
+ BOOST_HANA_CHECK(
+ hana::and_(hana::equal(a, b), hana::equal(b, c))
+ ^implies^ hana::equal(a, c)
+ );
+ });
+ }
+ };
+
+ template <typename C>
+ struct TestComparable<C, when<Constant<C>::value>>
+ : TestComparable<C, laws>
+ {
+ template <typename Xs>
+ TestComparable(Xs xs) : TestComparable<C, laws>{xs} {
+ foreach2(xs, [](auto a, auto b) {
+ BOOST_HANA_CHECK(
+ hana::value(hana::equal(a, b)) ^iff^
+ hana::equal(hana::value(a), hana::value(b))
+ );
+ });
+ }
+ };
+
+ template <typename P>
+ struct TestComparable<P, when<Product<P>::value>>
+ : TestComparable<P, laws>
+ {
+ template <typename Products>
+ TestComparable(Products products) : TestComparable<P, laws>{products} {
+ foreach2(products, [](auto x, auto y) {
+ BOOST_HANA_CHECK(
+ hana::equal(x, y) ^iff^
+ hana::and_(
+ hana::equal(hana::first(x), hana::first(y)),
+ hana::equal(hana::second(x), hana::second(y))
+ )
+ );
+ });
+ }
+ };
+
+ template <typename S>
+ struct TestComparable<S, when<Sequence<S>::value>>
+ : TestComparable<S, laws>
+ {
+ template <int i>
+ using x = _constant<i>;
+
+ template <typename Xs>
+ TestComparable(Xs xs) : TestComparable<S, laws>{xs} {
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // equal
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ list(),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal(
+ list(x<0>{}),
+ list()
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal(
+ list(),
+ list(x<0>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ list(x<0>{}),
+ list(x<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal(
+ list(x<0>{}, x<1>{}),
+ list(x<0>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ list(x<0>{}, x<1>{}),
+ list(x<0>{}, x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal(
+ list(x<0>{}, x<1>{}, x<2>{}, x<3>{}),
+ list(x<0>{}, x<1>{}, x<2>{}, x<4>{})
+ )));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_COMPARABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/constant.hpp b/src/boost/libs/hana/test/_include/laws/constant.hpp
new file mode 100644
index 000000000..1acd335e4
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/constant.hpp
@@ -0,0 +1,106 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_CONSTANT_HPP
+#define BOOST_HANA_TEST_LAWS_CONSTANT_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/concept/logical.hpp>
+
+#include <laws/base.hpp>
+#include <laws/comparable.hpp>
+#include <laws/euclidean_ring.hpp>
+#include <laws/group.hpp>
+#include <laws/logical.hpp>
+#include <laws/monoid.hpp>
+#include <laws/orderable.hpp>
+#include <laws/ring.hpp>
+
+#include <type_traits>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename C, typename = when<true>>
+ struct TestConstant {
+ using T = typename C::value_type;
+
+ template <typename X>
+ struct wrap_arbitrary_constant {
+ static constexpr bool value = boost::hana::value<X>();
+ using hana_tag = detail::CanonicalConstant<T>;
+ };
+
+ template <typename Xs, typename Convertibles>
+ TestConstant(Xs xs, Convertibles types) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(Constant<decltype(x)>{}, "");
+ });
+
+ hana::for_each(xs, hana::capture(types)([](auto types, auto c) {
+
+ // constexpr-ness of hana::value(c)
+ constexpr auto must_be_constexpr1 = hana::value(c);
+ constexpr auto must_be_constexpr2 = hana::value<decltype(c)>();
+ (void)must_be_constexpr1;
+ (void)must_be_constexpr2;
+
+ // consistency of C::value_type
+ static_assert(std::is_same<
+ T,
+ tag_of_t<decltype(hana::value(c))>
+ >{}, "");
+
+ // equivalence of value_of(c) and value<decltype(c)>
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value_of(c),
+ hana::value<decltype(c)>()
+ ));
+
+ // equivalence of value<decltype(c)>() and value(c)
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value<decltype(c)>(),
+ hana::value(c)
+ ));
+
+ // conversion from an arbitrary Constant
+ (void)to<C>(wrap_arbitrary_constant<decltype(c)>{});
+ static_assert(is_embedded<detail::CanonicalConstant<T>, C>{}, "");
+
+ hana::for_each(types, hana::capture(c)([](auto c, auto u) {
+ using U = typename decltype(u)::type;
+
+ // conversion to something to which the underlying data
+ // type can be converted.
+ BOOST_HANA_CHECK(equal(
+ to<U>(c),
+ make<U>(hana::value(c))
+ ));
+ static_assert(is_embedded<C, U>::value ^iff^ is_embedded<T, U>::value, "");
+
+ // common data type
+ static_assert(std::is_same<
+ common_t<C, detail::CanonicalConstant<U>>,
+ detail::CanonicalConstant<common_t<T, U>>
+ >{}, "");
+
+ static_assert(std::is_same<
+ common_t<detail::CanonicalConstant<U>, C>,
+ detail::CanonicalConstant<common_t<T, U>>
+ >{}, "");
+
+ static_assert(std::is_same<
+ common_t<C, U>,
+ common_t<typename C::value_type, U>
+ >{}, "");
+ }));
+ }));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_CONSTANT_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/euclidean_ring.hpp b/src/boost/libs/hana/test/_include/laws/euclidean_ring.hpp
new file mode 100644
index 000000000..96d1fce58
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/euclidean_ring.hpp
@@ -0,0 +1,99 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_EUCLIDEAN_RING_HPP
+#define BOOST_HANA_TEST_LAWS_EUCLIDEAN_RING_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/euclidean_ring.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/div.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/mod.hpp>
+#include <boost/hana/mult.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/value.hpp>
+#include <boost/hana/zero.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename D, typename = when<true>>
+ struct TestEuclideanRing : TestEuclideanRing<D, laws> {
+ using TestEuclideanRing<D, laws>::TestEuclideanRing;
+ };
+
+ template <typename D>
+ struct TestEuclideanRing<D, laws> {
+ template <typename Xs>
+ TestEuclideanRing(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(EuclideanRing<decltype(x)>{}, "");
+ });
+
+#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
+ zero<D>(); // force adding zero<D>'s member function to pending temploid list
+#endif
+
+ foreach2(xs, [](auto a, auto b) {
+
+ // commutativity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(a, b),
+ hana::mult(b, a)
+ ));
+
+ only_when_(hana::not_equal(b, zero<D>()),
+ hana::make_lazy([](auto a, auto b) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(
+ hana::mult(hana::div(a, b), b),
+ hana::mod(a, b)
+ ),
+ a
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mod(zero<D>(), b),
+ zero<D>()
+ ));
+ })(a, b));
+
+ });
+ }
+ };
+
+ template <typename C>
+ struct TestEuclideanRing<C, when<Constant<C>::value>>
+ : TestEuclideanRing<C, laws>
+ {
+ template <typename Xs>
+ TestEuclideanRing(Xs xs) : TestEuclideanRing<C, laws>{xs} {
+ foreach2(xs, [](auto x, auto y) {
+ only_when_(hana::not_equal(zero<C>(), y),
+ hana::make_lazy([](auto x, auto y) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::div(hana::value(x), hana::value(y)),
+ hana::value(hana::div(x, y))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mod(hana::value(x), hana::value(y)),
+ hana::value(hana::mod(x, y))
+ ));
+
+ })(x, y));
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_EUCLIDEAN_RING_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/foldable.hpp b/src/boost/libs/hana/test/_include/laws/foldable.hpp
new file mode 100644
index 000000000..57411f416
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/foldable.hpp
@@ -0,0 +1,1104 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_FOLDABLE_HPP
+#define BOOST_HANA_TEST_LAWS_FOLDABLE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/count.hpp>
+#include <boost/hana/count_if.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/fold.hpp>
+#include <boost/hana/fold_left.hpp>
+#include <boost/hana/fold_right.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/curry.hpp>
+#include <boost/hana/functional/demux.hpp>
+#include <boost/hana/functional/flip.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/maximum.hpp>
+#include <boost/hana/minimum.hpp>
+#include <boost/hana/monadic_fold_left.hpp>
+#include <boost/hana/monadic_fold_right.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/product.hpp>
+#include <boost/hana/reverse_fold.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/size.hpp>
+#include <boost/hana/sum.hpp>
+#include <boost/hana/unpack.hpp>
+#include <boost/hana/value.hpp>
+
+#include <laws/base.hpp>
+#include <support/identity.hpp>
+
+#include <vector>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename F, typename = when<true>>
+ struct TestFoldable : TestFoldable<F, laws> {
+ using TestFoldable<F, laws>::TestFoldable;
+ };
+
+ template <typename F>
+ struct TestFoldable<F, laws> {
+ template <typename Foldables>
+ TestFoldable(Foldables foldables) {
+ hana::for_each(foldables, [](auto xs) {
+ static_assert(Foldable<decltype(xs)>{}, "");
+
+ _injection<0> f{};
+ ct_eq<999> s{};
+
+ // equivalence of size(xs) and length(xs)
+ BOOST_HANA_CHECK(hana::equal(
+ hana::length(xs),
+ hana::size(xs)
+ ));
+
+ // equivalence of fold with fold_left and
+ // of reverse_fold with fold_right
+ BOOST_HANA_CHECK(hana::equal(
+ hana::fold(xs, s, f),
+ hana::fold_left(xs, s, f)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::reverse_fold(xs, s, f),
+ hana::fold_right(xs, s, hana::flip(f))
+ ));
+
+ only_when_(hana::not_equal(hana::length(xs), hana::size_c<0>),
+ hana::make_lazy([](auto f, auto xs) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::fold(xs, f),
+ hana::fold_left(xs, f)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::reverse_fold(xs, f),
+ hana::fold_right(xs, hana::flip(f))
+ ));
+ })(f, xs));
+
+ // equivalence of count(xs, val) and count_if(xs, equal.to(val))
+ struct not_there { };
+ BOOST_HANA_CHECK(hana::equal(
+ hana::count(xs, not_there{}),
+ hana::count_if(xs, equal.to(not_there{}))
+ ));
+
+ hana::for_each(xs, hana::capture(xs)([](auto xs, auto value) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::count(xs, value),
+ hana::count_if(xs, equal.to(value))
+ ));
+ }));
+ });
+ }
+ };
+
+ template <typename P>
+ struct TestFoldable<P, when<Product<P>::value>>
+ : TestFoldable<P, laws>
+ {
+ template <typename Products>
+ TestFoldable(Products products) : TestFoldable<P, laws>{products} {
+ hana::for_each(products, [](auto p) {
+ _injection<0> f{};
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::unpack(p, f),
+ f(hana::first(p), hana::second(p))
+ ));
+ });
+ }
+ };
+
+ template <typename S>
+ struct TestFoldable<S, when<Sequence<S>::value>>
+ : TestFoldable<S, laws>
+ {
+ template <int i>
+ using x = _constant<i>;
+
+ template <int i>
+ using ord = _constant<i>;
+
+ struct undefined { };
+
+ template <typename Xs>
+ TestFoldable(Xs xs) : TestFoldable<S, laws>{xs} {
+ _injection<0> f{};
+ auto z = x<999>{};
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // fold_left (with initial state)
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(), z, undefined{}),
+ z
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(x<1>{}), z, f),
+ f(z, x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(x<1>{}, x<2>{}), z, f),
+ f(f(z, x<1>{}), x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(x<1>{}, x<2>{}, x<3>{}), z, f),
+ f(f(f(z, x<1>{}), x<2>{}), x<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), z, f),
+ f(f(f(f(z, x<1>{}), x<2>{}), x<3>{}), x<4>{})
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_left(list(1), z, f),
+ f(z, 1)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_left(list(1, '2'), z, f),
+ f(f(z, 1), '2')
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_left(list(1, '2', 3.3), z, f),
+ f(f(f(z, 1), '2'), 3.3)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_left(list(1, '2', 3.3, 4.4f), z, f),
+ f(f(f(f(z, 1), '2'), 3.3), 4.4f)
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // fold_left (without initial state)
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(z), undefined{}),
+ z
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(z, x<2>{}), f),
+ f(z, x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(z, x<2>{}, x<3>{}), f),
+ f(f(z, x<2>{}), x<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_left(list(z, x<2>{}, x<3>{}, x<4>{}), f),
+ f(f(f(z, x<2>{}), x<3>{}), x<4>{})
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // fold_right (with initial state)
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(), z, undefined{}),
+ z
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<0>{}), z, f),
+ f(x<0>{}, z)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<0>{}, x<1>{}), z, f),
+ f(x<0>{}, f(x<1>{}, z))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<0>{}, x<1>{}, x<2>{}), z, f),
+ f(x<0>{}, f(x<1>{}, f(x<2>{}, z)))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<0>{}, x<1>{}, x<2>{}, x<3>{}), z, f),
+ f(x<0>{}, f(x<1>{}, f(x<2>{}, f(x<3>{}, z))))
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_right(list(1), z, f),
+ f(1, z)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_right(list(1, '2'), z, f),
+ f(1, f('2', z))
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_right(list(1, '2', 3.3), z, f),
+ f(1, f('2', f(3.3, z)))
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ fold_right(list(1, '2', 3.3, 4.4f), z, f),
+ f(1, f('2', f(3.3, f(4.4f, z))))
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // fold_right (without initial state)
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(z), undefined{}),
+ z
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<1>{}, z), f),
+ f(x<1>{}, z)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<1>{}, x<2>{}, z), f),
+ f(x<1>{}, f(x<2>{}, z))
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ fold_right(list(x<1>{}, x<2>{}, x<3>{}, z), f),
+ f(x<1>{}, f(x<2>{}, f(x<3>{}, z)))
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // monadic_fold_left (with initial state)
+ //////////////////////////////////////////////////////////////////
+ {
+ using M = ::Identity;
+ auto f = hana::demux(::identity)(test::_injection<0>{});
+ auto s = x<999>{};
+ auto fp = hana::curry<2>(hana::flip(f));
+ constexpr auto mfold = monadic_fold_left<M>;
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(), s, undefined{}),
+ lift<M>(s)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}), s, f),
+ f(s, x<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}), s, f),
+ chain(f(s, x<1>{}), fp(x<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}), s, f),
+ chain(chain(f(s, x<1>{}), fp(x<2>{})), fp(x<3>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), s, f),
+ chain(chain(chain(f(s, x<1>{}), fp(x<2>{})), fp(x<3>{})), fp(x<4>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), s, f),
+ chain(chain(chain(chain(f(s, x<1>{}), fp(x<2>{})), fp(x<3>{})), fp(x<4>{})), fp(x<5>{}))
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // monadic_fold_left (without initial state)
+ //////////////////////////////////////////////////////////////////
+ {
+ using M = ::Identity;
+ auto f = hana::demux(::identity)(test::_injection<0>{});
+ auto fp = hana::curry<2>(hana::flip(f));
+ constexpr auto mfold = monadic_fold_left<M>;
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}), undefined{}),
+ lift<M>(x<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}), f),
+ f(x<1>{}, x<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}), f),
+ chain(f(x<1>{}, x<2>{}), fp(x<3>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), f),
+ chain(chain(f(x<1>{}, x<2>{}), fp(x<3>{})), fp(x<4>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), f),
+ chain(chain(chain(f(x<1>{}, x<2>{}), fp(x<3>{})), fp(x<4>{})), fp(x<5>{}))
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // monadic_fold_right (with initial state)
+ //////////////////////////////////////////////////////////////////
+ {
+ using M = ::Identity;
+ auto f = hana::demux(::identity)(test::_injection<0>{});
+ auto s = x<999>{};
+ auto fp = hana::curry<2>(f);
+ // flipping `chain` makes the right associativity easier to see
+ auto chain = hana::flip(hana::chain);
+ constexpr auto mfold = monadic_fold_right<M>;
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(), s, undefined{}),
+ lift<M>(s)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}), s, f),
+ f(x<1>{}, s)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}), s, f),
+ chain(fp(x<1>{}), f(x<2>{}, s))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}), s, f),
+ chain(fp(x<1>{}), chain(fp(x<2>{}), f(x<3>{}, s)))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), s, f),
+ chain(fp(x<1>{}), chain(fp(x<2>{}), chain(fp(x<3>{}), f(x<4>{}, s))))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), s, f),
+ chain(fp(x<1>{}), chain(fp(x<2>{}), chain(fp(x<3>{}), chain(fp(x<4>{}), f(x<5>{}, s)))))
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // monadic_fold_right (without initial state)
+ //////////////////////////////////////////////////////////////////
+ {
+ using M = ::Identity;
+ auto f = hana::demux(::identity)(test::_injection<0>{});
+ auto fp = hana::curry<2>(f);
+ // flipping `chain` makes the right associativity easier to see
+ auto chain = hana::flip(hana::chain);
+ constexpr auto mfold = monadic_fold_right<M>;
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}), undefined{}),
+ lift<M>(x<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}), f),
+ f(x<1>{}, x<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}), f),
+ chain(fp(x<1>{}), f(x<2>{}, x<3>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), f),
+ chain(fp(x<1>{}), chain(fp(x<2>{}), f(x<3>{}, x<4>{})))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), f),
+ chain(fp(x<1>{}), chain(fp(x<2>{}), chain(fp(x<3>{}), f(x<4>{}, x<5>{}))))
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // length
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ length(list()), size_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ length(list(undefined{})), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ length(list(undefined{}, undefined{})), size_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ length(list(undefined{}, undefined{}, undefined{})), size_c<3>
+ ));
+
+ int i = 0; // non-constexpr
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ length(list(i, i)),
+ size_c<2>
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // maximum (without a custom predicate)
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{})),
+ ord<0>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{}, ord<1>{})),
+ ord<1>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<0>{})),
+ ord<1>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{}, ord<1>{}, ord<2>{})),
+ ord<2>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<0>{}, ord<2>{})),
+ ord<2>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<2>{}, ord<0>{})),
+ ord<2>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<2>{}, ord<1>{}, ord<0>{})),
+ ord<2>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<2>{}, ord<0>{}, ord<1>{})),
+ ord<2>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{}, ord<1>{}, ord<2>{}, ord<3>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<0>{}, ord<2>{}, ord<3>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<2>{}, ord<0>{}, ord<3>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<1>{}, ord<2>{}, ord<3>{}, ord<0>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<2>{}, ord<1>{}, ord<3>{}, ord<0>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<2>{}, ord<3>{}, ord<1>{}, ord<0>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<2>{}, ord<3>{}, ord<0>{}, ord<1>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<3>{}, ord<2>{}, ord<0>{}, ord<1>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<3>{}, ord<0>{}, ord<2>{}, ord<1>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<3>{}, ord<0>{}, ord<1>{}, ord<2>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{}, ord<2>{}, ord<3>{}, ord<1>{})),
+ ord<3>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ maximum(list(ord<0>{}, ord<3>{}, ord<1>{}, ord<2>{})),
+ ord<3>{}
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0})),
+ int{0}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, long{1})),
+ long{1}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, long{0})),
+ int{1}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, 1ll, long{2})),
+ long{2}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, 0ll, long{2})),
+ long{2}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, 2ll, long{0})),
+ 2ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{2}, 1ll, long{0})),
+ int{2}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{2}, 0ll, long{1})),
+ int{2}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, 1ll, long{2}, short{3})),
+ short{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, 0ll, long{2}, short{3})),
+ short{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, 2ll, long{0}, short{3})),
+ short{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{1}, 2ll, long{3}, short{0})),
+ long{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{2}, 1ll, long{3}, short{0})),
+ long{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{2}, 3ll, long{1}, short{0})),
+ 3ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{2}, 3ll, long{0}, short{1})),
+ 3ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{3}, 2ll, long{0}, short{1})),
+ int{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{3}, 0ll, long{2}, short{1})),
+ int{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{3}, 0ll, long{1}, short{2})),
+ int{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, 2ll, long{3}, short{1})),
+ long{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, 3ll, long{1}, short{2})),
+ 3ll
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, 1ll, long_c<2>)),
+ long{2}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ maximum(list(int{0}, long_c<1>, 2ll)),
+ 2ll
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // minimum (without a custom predicate)
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{})),
+ ord<6>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{}, ord<7>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<6>{})),
+ ord<6>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{}, ord<7>{}, ord<8>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<6>{}, ord<8>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<8>{}, ord<6>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<8>{}, ord<7>{}, ord<6>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<8>{}, ord<6>{}, ord<7>{})),
+ ord<6>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{}, ord<7>{}, ord<8>{}, ord<9>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<6>{}, ord<8>{}, ord<9>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<8>{}, ord<6>{}, ord<9>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<7>{}, ord<8>{}, ord<9>{}, ord<6>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<8>{}, ord<7>{}, ord<9>{}, ord<6>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<8>{}, ord<9>{}, ord<7>{}, ord<6>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<8>{}, ord<9>{}, ord<6>{}, ord<7>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<9>{}, ord<8>{}, ord<6>{}, ord<7>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<9>{}, ord<6>{}, ord<8>{}, ord<7>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<9>{}, ord<6>{}, ord<7>{}, ord<8>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{}, ord<8>{}, ord<9>{}, ord<7>{})),
+ ord<6>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ minimum(list(ord<6>{}, ord<9>{}, ord<7>{}, ord<8>{})),
+ ord<6>{}
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{4})),
+ int{4}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{4}, short{5})),
+ int{4}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{5}, short{4})),
+ short{4}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{4}, short{5}, long{6})),
+ int{4}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{7}, short{6}, long{8})),
+ short{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{7}, short{8}, long{6})),
+ long{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{8}, short{7}, long{6})),
+ long{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{8}, short{6}, long{7})),
+ short{6}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{6}, short{7}, long{8}, 9ll)),
+ int{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{7}, short{6}, long{8}, 9ll)),
+ short{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{7}, short{8}, long{6}, 9ll)),
+ long{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{7}, short{8}, long{9}, 6ll)),
+ 6ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{8}, short{7}, long{9}, 6ll)),
+ 6ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{8}, short{9}, long{7}, 6ll)),
+ 6ll
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{8}, short{9}, long{6}, 7ll)),
+ long{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{9}, short{8}, long{6}, 7ll)),
+ long{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{9}, short{6}, long{8}, 7ll)),
+ short{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{9}, short{6}, long{7}, 8ll)),
+ short{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{6}, short{8}, long{9}, 7ll)),
+ int{6}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{6}, short{9}, long{7}, 8ll)),
+ int{6}
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(int{3}, short{4}, long_c<5>)),
+ int{3}
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ minimum(list(ord<33>{}, short{45}, long{46})),
+ ord<33>{}
+ ));
+ }
+
+
+ //////////////////////////////////////////////////////////////////
+ // count_if
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(), id), size_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>), id), size_c<0>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<1>), id), size_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<0>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<1>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<0>), id), size_c<0>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<1>, long_c<1>), id), size_c<3>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<1>, long_c<0>), id), size_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<0>, long_c<1>), id), size_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<1>, char_c<0>, long_c<0>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<1>, long_c<1>), id), size_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<1>, long_c<0>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<0>, long_c<1>), id), size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ count_if(list(int_c<0>, char_c<0>, long_c<0>), id), size_c<0>
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}), id), 0u
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{1}), id), 2u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{0}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{1}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{0}), id), 0u
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{1}, double{1}), id), 3u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{1}, double{0}), id), 2u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{0}, double{1}), id), 2u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{1}, char{0}, double{0}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{1}, double{1}), id), 2u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{1}, double{0}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{0}, double{1}), id), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(int{0}, char{0}, double{0}), id), 0u
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_LAMBDA auto is_even = [](auto x) {
+ return x % 2 == 0;
+ };
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(), is_even), 0u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(1), is_even), 0u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(2), is_even), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(1, 2), is_even), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(1, 2, 3), is_even), 1u
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ count_if(list(1, 2, 3, 4), is_even), 2u
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // count
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(), undefined{}),
+ size_c<0>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}), undefined{}),
+ size_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}), ct_eq<0>{}),
+ size_c<1>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}, ct_eq<1>{}), undefined{}),
+ size_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}, ct_eq<1>{}), ct_eq<0>{}),
+ size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}, ct_eq<1>{}), ct_eq<1>{}),
+ size_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::count(list(ct_eq<0>{}, ct_eq<0>{}), ct_eq<0>{}),
+ size_c<2>
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // product
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<int>>(list()),
+ int_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<int>>(list(int_c<2>)),
+ int_c<2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<int>>(list(int_c<2>, int_c<3>)),
+ int_c<2 * 3>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<int>>(list(int_c<2>, int_c<3>, int_c<4>)),
+ int_c<2 * 3 * 4>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<int>>(list(int_c<2>, int_c<3>, int_c<4>, int_c<5>)),
+ int_c<2 * 3 * 4 * 5>
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<unsigned long>>(list()),
+ ulong_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ product<integral_constant_tag<unsigned long>>(list(ulong_c<2>, ulong_c<3>, ulong_c<4>)),
+ ulong_c<2 * 3 * 4>
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ product<int>(list(2)),
+ 2
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ product<int>(list(2, 3)),
+ 2 * 3
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ product<int>(list(2, 3, 4)),
+ 2 * 3 * 4
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ product<int>(list(2, 3, 4, 5)),
+ 2 * 3 * 4 * 5
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // sum
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<int>>(list()),
+ int_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<int>>(list(int_c<1>)),
+ int_c<1>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<int>>(list(int_c<1>, int_c<2>)),
+ int_c<1 + 2>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<int>>(list(int_c<1>, int_c<2>, int_c<3>)),
+ int_c<1 + 2 + 3>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<int>>(list(int_c<1>, int_c<2>, int_c<3>, int_c<4>)),
+ int_c<1 + 2 + 3 + 4>
+ ));
+
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<unsigned long>>(list()),
+ ulong_c<0>
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ sum<integral_constant_tag<unsigned long>>(list(ulong_c<1>, ulong_c<2>, ulong_c<3>)),
+ ulong_c<1 + 2 + 3>
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ sum<int>(list(1)), 1
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ sum<int>(list(1, 2)), 1 + 2
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ sum<int>(list(1, 2, 3)), 1 + 2 + 3
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ sum<int>(list(1, 2, 3, 4)), 1 + 2 + 3 + 4
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // unpack
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ unpack(list(), f),
+ f()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ unpack(list(x<0>{}), f),
+ f(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ unpack(list(x<0>{}, x<1>{}), f),
+ f(x<0>{}, x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ unpack(list(x<0>{}, x<1>{}, x<2>{}), f),
+ f(x<0>{}, x<1>{}, x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ unpack(list(x<0>{}, x<1>{}, x<2>{}, x<3>{}), f),
+ f(x<0>{}, x<1>{}, x<2>{}, x<3>{})
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_FOLDABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/functor.hpp b/src/boost/libs/hana/test/_include/laws/functor.hpp
new file mode 100644
index 000000000..d1ddbb4de
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/functor.hpp
@@ -0,0 +1,250 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_FUNCTOR_HPP
+#define BOOST_HANA_TEST_LAWS_FUNCTOR_HPP
+
+#include <boost/hana/adjust.hpp>
+#include <boost/hana/adjust_if.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/functor.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/eval_if.hpp>
+#include <boost/hana/fill.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/replace.hpp>
+#include <boost/hana/replace_if.hpp>
+#include <boost/hana/transform.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename F, typename = when<true>>
+ struct TestFunctor : TestFunctor<F, laws> {
+ using TestFunctor<F, laws>::TestFunctor;
+ };
+
+ template <typename F>
+ struct TestFunctor<F, laws> {
+ template <typename Xs, typename Elements>
+ TestFunctor(Xs xs, Elements elements) {
+ hana::for_each(xs, hana::capture(elements)([](auto elements, auto x) {
+ static_assert(Functor<decltype(x)>{}, "");
+
+ test::_injection<0> f{};
+ test::_injection<1> g{};
+
+ // identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::transform(x, id),
+ x
+ ));
+
+ // composition
+ BOOST_HANA_CHECK(hana::equal(
+ hana::transform(x, hana::compose(f, g)),
+ hana::transform(hana::transform(x, g), f)
+ ));
+
+ // method definitions in terms of transform/adjust_if
+ hana::for_each(elements, hana::capture(x, f, elements)(
+ [](auto x, auto f, auto elements, auto value) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::adjust(x, value, f),
+ hana::adjust_if(x, hana::equal.to(value), f)
+ ));
+
+ hana::for_each(elements, hana::capture(x, value)(
+ [](auto x, auto oldval, auto newval) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::replace(x, oldval, newval),
+ hana::replace_if(x, hana::equal.to(oldval), newval)
+ ));
+ }));
+ }));
+
+ auto pred = hana::always(true_c);
+ BOOST_HANA_CHECK(hana::equal(
+ hana::adjust_if(x, pred, f),
+ hana::transform(x, [=](auto z) {
+ return hana::eval_if(pred(z),
+ hana::make_lazy(f)(z),
+ hana::make_lazy(z)
+ );
+ })
+ ));
+
+ test::_constant<0> v{};
+ BOOST_HANA_CHECK(hana::equal(
+ hana::replace_if(x, pred, v),
+ hana::adjust_if(x, pred, hana::always(v))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::fill(x, v),
+ hana::replace_if(x, hana::always(true_c), v)
+ ));
+
+ }));
+ }
+ };
+
+ template <typename S>
+ struct TestFunctor<S, when<Sequence<S>::value>>
+ : TestFunctor<S, laws>
+ {
+ struct undefined { };
+
+ template <typename Xs, typename Elements>
+ TestFunctor(Xs xs, Elements elements)
+ : TestFunctor<S, laws>{xs, elements}
+ {
+ using test::ct_eq;
+ using test::cx_eq;
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // replace_if
+ //////////////////////////////////////////////////////////////////
+ {
+ auto a = ct_eq<888>{};
+ auto b = ct_eq<999>{};
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(), undefined{}, undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}), equal.to(a), undefined{}),
+ list(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a), equal.to(a), b),
+ list(b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}), equal.to(a), undefined{}),
+ list(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a, ct_eq<1>{}), equal.to(a), b),
+ list(b, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}, a), equal.to(a), b),
+ list(ct_eq<0>{}, b)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a, a), equal.to(a), b),
+ list(b, b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), equal.to(a), undefined{}),
+ list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a, ct_eq<1>{}, ct_eq<2>{}), equal.to(a), b),
+ list(b, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}, a, ct_eq<2>{}), equal.to(a), b),
+ list(ct_eq<0>{}, b, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}, a), equal.to(a), b),
+ list(ct_eq<0>{}, ct_eq<1>{}, b)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a, ct_eq<1>{}, a), equal.to(a), b),
+ list(b, ct_eq<1>{}, b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace_if(list(a, ct_eq<1>{}, a, ct_eq<3>{}, a), equal.to(a), b),
+ list(b, ct_eq<1>{}, b, ct_eq<3>{}, b)
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // replace
+ //////////////////////////////////////////////////////////////////
+ {
+ auto a = ct_eq<888>{};
+ auto b = ct_eq<999>{};
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(), undefined{}, undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}), a, undefined{}),
+ list(ct_eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a), a, b),
+ list(b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}, ct_eq<1>{}), a, undefined{}),
+ list(ct_eq<0>{}, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a, ct_eq<1>{}), a, b),
+ list(b, ct_eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}, a), a, b),
+ list(ct_eq<0>{}, b)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a, a), a, b),
+ list(b, b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), a, undefined{}),
+ list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a, ct_eq<1>{}, ct_eq<2>{}), a, b),
+ list(b, ct_eq<1>{}, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}, a, ct_eq<2>{}), a, b),
+ list(ct_eq<0>{}, b, ct_eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(ct_eq<0>{}, ct_eq<1>{}, a), a, b),
+ list(ct_eq<0>{}, ct_eq<1>{}, b)
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a, ct_eq<1>{}, a), a, b),
+ list(b, ct_eq<1>{}, b)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::replace(list(a, ct_eq<1>{}, a, ct_eq<3>{}, a), a, b),
+ list(b, ct_eq<1>{}, b, ct_eq<3>{}, b)
+ ));
+ }
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_FUNCTOR_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/group.hpp b/src/boost/libs/hana/test/_include/laws/group.hpp
new file mode 100644
index 000000000..b9eeab776
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/group.hpp
@@ -0,0 +1,93 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_GROUP_HPP
+#define BOOST_HANA_TEST_LAWS_GROUP_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/concept/group.hpp>
+#include <boost/hana/lazy.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename G, typename = when<true>>
+ struct TestGroup : TestGroup<G, laws> {
+ using TestGroup<G, laws>::TestGroup;
+ };
+
+ template <typename G>
+ struct TestGroup<G, laws> {
+ template <typename Xs>
+ TestGroup(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(Group<decltype(x)>{}, "");
+ });
+
+#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
+ zero<G>(); // force adding zero<G>'s member function to pending temploid list
+#endif
+
+ foreach2(xs, [](auto x, auto y) {
+
+ // left inverse
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(x, hana::negate(x)),
+ zero<G>()
+ ));
+
+ // right inverse
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(hana::negate(x), x),
+ zero<G>()
+ ));
+
+ // default definition of minus
+ BOOST_HANA_CHECK(hana::equal(
+ hana::minus(x, y),
+ hana::plus(x, hana::negate(y))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::minus(y, x),
+ hana::plus(y, hana::negate(x))
+ ));
+
+ // default definition of negate
+ BOOST_HANA_CHECK(hana::equal(
+ hana::negate(hana::negate(x)),
+ x
+ ));
+ });
+ }
+ };
+
+ template <typename C>
+ struct TestGroup<C, when<Constant<C>::value>>
+ : TestGroup<C, laws>
+ {
+ template <typename Xs>
+ TestGroup(Xs xs) : TestGroup<C, laws>{xs} {
+ foreach2(xs, [](auto x, auto y) {
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::negate(hana::value(x)),
+ hana::value(hana::negate(x))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::minus(hana::value(x), hana::value(y)),
+ hana::value(hana::minus(x, y))
+ ));
+
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_GROUP_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/hashable.hpp b/src/boost/libs/hana/test/_include/laws/hashable.hpp
new file mode 100644
index 000000000..0fbd8f333
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/hashable.hpp
@@ -0,0 +1,60 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_HASHABLE_HPP
+#define BOOST_HANA_TEST_LAWS_HASHABLE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/hashable.hpp>
+#include <boost/hana/core/default.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/hash.hpp>
+#include <boost/hana/if.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename G, typename = when<true>>
+ struct TestHashable : TestHashable<G, laws> {
+ using TestHashable<G, laws>::TestHashable;
+ };
+
+ template <typename H>
+ struct TestHashable<H, laws> {
+ template <typename Xs>
+ TestHashable(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(Hashable<decltype(x)>{}, "");
+ });
+
+ hana::for_each(xs, [&](auto const& x) {
+ hana::for_each(xs, [&](auto const& y) {
+ using X = hana::tag_of_t<decltype(x)>;
+ using Y = hana::tag_of_t<decltype(y)>;
+ constexpr bool comparable = !hana::is_default<
+ hana::equal_impl<X, Y>
+ >::value;
+
+ hana::if_(hana::bool_c<comparable>,
+ [](auto const& x, auto const& y) {
+ BOOST_HANA_CHECK(
+ hana::equal(x, y)
+ ^implies^
+ hana::equal(hana::hash(x), hana::hash(y))
+ );
+ },
+ [](auto...) { }
+ )(x, y);
+ });
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_HASHABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/iterable.hpp b/src/boost/libs/hana/test/_include/laws/iterable.hpp
new file mode 100644
index 000000000..d6d84c5ec
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/iterable.hpp
@@ -0,0 +1,195 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_ITERABLE_HPP
+#define BOOST_HANA_TEST_LAWS_ITERABLE_HPP
+
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/at.hpp>
+#include <boost/hana/back.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/foldable.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/to.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/drop_front.hpp>
+#include <boost/hana/drop_front_exactly.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/eval_if.hpp>
+#include <boost/hana/find_if.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/front.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/is_empty.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/length.hpp>
+#include <boost/hana/minus.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/range.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename It, typename = hana::when<true>>
+ struct TestIterable : TestIterable<It, laws> {
+ using TestIterable<It, laws>::TestIterable;
+ };
+
+ template <typename It>
+ struct TestIterable<It, laws> {
+ template <typename Xs>
+ TestIterable(Xs xs) {
+ hana::for_each(xs, [](auto xs) {
+ static_assert(Iterable<decltype(xs)>{}, "");
+
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::is_empty(xs) ^iff^ hana::is_empty(hana::to<tuple_tag>(xs))
+ );
+
+ only_when_(hana::not_(hana::is_empty(xs)), hana::make_lazy([](auto xs) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::front(xs),
+ hana::front(hana::to<tuple_tag>(xs))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::to<tuple_tag>(hana::drop_front_exactly(xs)),
+ hana::drop_front_exactly(hana::to<tuple_tag>(xs))
+ ));
+
+ // methods
+ // back(xs) == at(xs, length(xs)-1)
+ BOOST_HANA_CHECK(hana::equal(
+ hana::back(xs),
+ hana::at(xs, hana::minus(hana::length(xs), hana::size_c<1>))
+ ));
+
+ })(xs));
+
+ // drop_front(xs, 0) == xs
+ BOOST_HANA_CHECK(hana::equal(
+ hana::drop_front(xs, size_c<0>),
+ xs
+ ));
+
+ // at(xs, n) == front(drop_front(xs, n))
+ hana::for_each(hana::make_range(size_c<0>, hana::length(xs)),
+ hana::capture(xs)([](auto xs, auto n) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::at(xs, n),
+ hana::front(hana::drop_front(xs, n))
+ ));
+ }));
+
+ // Searchable
+ hana::eval_if(hana::is_empty(xs),
+ hana::make_lazy([](auto xs) {
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(xs, hana::always(true_c)))
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::find_if(xs, hana::always(true_c)),
+ nothing
+ ));
+ })(xs),
+ hana::make_lazy([](auto xs) {
+ BOOST_HANA_CHECK(
+ hana::any_of(xs, hana::always(true_c))
+ );
+ BOOST_HANA_CHECK(
+ hana::not_(hana::any_of(xs, hana::always(false_c)))
+ );
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::find_if(xs, hana::always(true_c)),
+ hana::just(hana::front(xs))
+ ));
+ })(xs)
+ );
+
+ });
+ }
+ };
+
+ template <typename S>
+ struct TestIterable<S, when<Sequence<S>::value>>
+ : TestIterable<S, laws>
+ {
+ template <int i>
+ using x = ct_eq<i>;
+
+ template <int i = 0>
+ struct invalid { };
+
+ struct undefined { };
+
+ template <typename Xs>
+ TestIterable(Xs xs) : TestIterable<S, laws>{xs} {
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // front
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ front(list(x<0>{})),
+ x<0>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ front(list(x<0>{}, invalid<>{})),
+ x<0>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ front(list(x<0>{}, invalid<1>{}, invalid<2>{})),
+ x<0>{}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ front(list(1)), 1
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ front(list(1, '2')), 1
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ front(list(1, '2', 3.3)), 1
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // back
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ back(list(x<0>{})),
+ x<0>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ back(list(invalid<0>{}, x<1>{})),
+ x<1>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ back(list(invalid<0>{}, invalid<1>{}, x<2>{})),
+ x<2>{}
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ back(list(1)), 1
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ back(list(1, '2')), '2'
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ back(list(1, '2', 3.3)), 3.3
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_ITERABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/logical.hpp b/src/boost/libs/hana/test/_include/laws/logical.hpp
new file mode 100644
index 000000000..df9932766
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/logical.hpp
@@ -0,0 +1,137 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_LOGICAL_HPP
+#define BOOST_HANA_TEST_LAWS_LOGICAL_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/concept/logical.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename L, typename = when<true>>
+ struct TestLogical : TestLogical<L, laws> {
+ using TestLogical<L, laws>::TestLogical;
+ };
+
+ template <typename L>
+ struct TestLogical<L, laws> {
+ template <typename Xs, typename Pred, typename F>
+ static void for_each_such_that(Xs xs, Pred pred, F f) {
+ hana::for_each(xs, [&pred, &f](auto x) {
+ hana::eval_if(pred(x),
+ hana::make_lazy(f)(x),
+ [](auto) { }
+ );
+ });
+ }
+
+ template <typename Xs>
+ TestLogical(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(Logical<decltype(x)>{}, "");
+ });
+
+ foreach3(xs, hana::capture(xs)([](auto xs, auto a, auto b, auto c) {
+ auto true_valued = [](auto x) {
+ return hana::if_(x, true_c, false_c);
+ };
+ auto false_valued = [](auto x) {
+ return hana::if_(x, false_c, true_c);
+ };
+
+ // associativity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::or_(a, hana::or_(b, c)),
+ hana::or_(hana::or_(a, b), c)
+ ));
+ BOOST_HANA_CHECK(hana::equal(
+ hana::and_(a, hana::and_(b, c)),
+ hana::and_(hana::and_(a, b), c)
+ ));
+
+ // equivalence through commutativity
+ BOOST_HANA_CHECK(
+ hana::or_(a, b) ^iff^ hana::or_(b, a)
+ );
+ BOOST_HANA_CHECK(
+ hana::and_(a, b) ^iff^ hana::and_(b, a)
+ );
+
+ // absorption
+ BOOST_HANA_CHECK(hana::equal(
+ hana::or_(a, hana::and_(a, b)), a
+ ));
+ BOOST_HANA_CHECK(hana::equal(
+ hana::and_(a, hana::or_(a, b)), a
+ ));
+
+ // left identity
+ TestLogical::for_each_such_that(xs, true_valued,
+ hana::capture(a)([](auto a, auto t) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::and_(t, a), a
+ ));
+ }));
+ TestLogical::for_each_such_that(xs, false_valued,
+ hana::capture(a)([](auto a, auto f) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::or_(f, a), a
+ ));
+ }));
+
+ // distributivity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::or_(a, hana::and_(b, c)),
+ hana::and_(hana::or_(a, b), hana::or_(a, c))
+ ));
+ BOOST_HANA_CHECK(hana::equal(
+ hana::and_(a, hana::or_(b, c)),
+ hana::or_(hana::and_(a, b), hana::and_(a, c))
+ ));
+
+ // complements
+ BOOST_HANA_CHECK(true_valued(hana::or_(a, hana::not_(a))));
+ BOOST_HANA_CHECK(false_valued(hana::and_(a, hana::not_(a))));
+
+ }));
+ }
+ };
+
+ template <typename C>
+ struct TestLogical<C, when<Constant<C>::value>>
+ : TestLogical<C, laws>
+ {
+ template <typename Xs>
+ TestLogical(Xs xs) : TestLogical<C, laws>{xs} {
+ foreach2(xs, [](auto x, auto y) {
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value(hana::not_(x)),
+ hana::not_(hana::value(x))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value(hana::and_(x, y)),
+ hana::and_(hana::value(x), hana::value(y))
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value(hana::or_(x, y)),
+ hana::or_(hana::value(x), hana::value(y))
+ ));
+
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_LOGICAL_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/monad.hpp b/src/boost/libs/hana/test/_include/laws/monad.hpp
new file mode 100644
index 000000000..25a23d417
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/monad.hpp
@@ -0,0 +1,222 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_MONAD_HPP
+#define BOOST_HANA_TEST_LAWS_MONAD_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/monad.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/flatten.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/id.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/monadic_compose.hpp>
+#include <boost/hana/transform.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename M, typename = when<true>>
+ struct TestMonad : TestMonad<M, laws> {
+ using TestMonad<M, laws>::TestMonad;
+ };
+
+ template <typename M>
+ struct TestMonad<M, laws> {
+ // Xs are Monads over something
+ // XXs are Monads over Monads over something
+ template <typename Xs, typename XXs>
+ TestMonad(Xs xs, XXs xxs) {
+ hana::for_each(xs, [](auto m) {
+ static_assert(Monad<decltype(m)>{}, "");
+
+ auto f = hana::compose(lift<M>, test::_injection<0>{});
+ auto g = hana::compose(lift<M>, test::_injection<1>{});
+ auto h = hana::compose(lift<M>, test::_injection<2>{});
+ auto x = test::ct_eq<0>{};
+
+ //////////////////////////////////////////////////////////////
+ // Laws formulated with `monadic_compose`
+ //////////////////////////////////////////////////////////////
+ // associativity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::monadic_compose(h, hana::monadic_compose(g, f))(x),
+ hana::monadic_compose(hana::monadic_compose(h, g), f)(x)
+ ));
+
+ // left identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::monadic_compose(lift<M>, f)(x),
+ f(x)
+ ));
+
+ // right identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::monadic_compose(f, lift<M>)(x),
+ f(x)
+ ));
+
+ //////////////////////////////////////////////////////////////
+ // Laws formulated with `chain`
+ //
+ // This just provides us with some additional cross-checking,
+ // but the documentation does not mention those.
+ //////////////////////////////////////////////////////////////
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(hana::lift<M>(x), f),
+ f(x)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(m, lift<M>),
+ m
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(m, [f, g](auto x) {
+ return hana::chain(f(x), g);
+ }),
+ hana::chain(hana::chain(m, f), g)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::transform(m, f),
+ hana::chain(m, hana::compose(lift<M>, f))
+ ));
+
+ //////////////////////////////////////////////////////////////
+ // Consistency of method definitions
+ //////////////////////////////////////////////////////////////
+ // consistency of `chain`
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(m, f),
+ hana::flatten(hana::transform(m, f))
+ ));
+
+ // consistency of `monadic_compose`
+ BOOST_HANA_CHECK(hana::equal(
+ hana::monadic_compose(f, g)(x),
+ hana::chain(g(x), f)
+ ));
+ });
+
+ // consistency of `flatten`
+ hana::for_each(xxs, [](auto mm) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::flatten(mm),
+ hana::chain(mm, hana::id)
+ ));
+ });
+ }
+ };
+
+ template <typename S>
+ struct TestMonad<S, when<Sequence<S>::value>>
+ : TestMonad<S, laws>
+ {
+ template <typename Xs, typename XXs>
+ TestMonad(Xs xs, XXs xxs)
+ : TestMonad<S, laws>{xs, xxs}
+ {
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // flatten
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(list(list(), list())),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(list(list(ct_eq<0>{}), list())),
+ list(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(list(list(), list(ct_eq<0>{}))),
+ list(ct_eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(list(list(ct_eq<0>{}), list(ct_eq<1>{}))),
+ list(ct_eq<0>{}, ct_eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::flatten(list(
+ list(ct_eq<0>{}, ct_eq<1>{}),
+ list(),
+ list(ct_eq<2>{}, ct_eq<3>{}),
+ list(ct_eq<4>{})
+ )),
+ list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{})
+ ));
+
+ // just make sure we don't double move; this happened in hana::tuple
+ hana::flatten(list(list(Tracked{1}, Tracked{2})));
+
+ //////////////////////////////////////////////////////////////////
+ // chain
+ //////////////////////////////////////////////////////////////////
+ {
+ test::_injection<0> f{};
+ auto g = hana::compose(list, f);
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::chain(list(), g),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::chain(list(ct_eq<1>{}), g),
+ list(f(ct_eq<1>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::chain(list(ct_eq<1>{}, ct_eq<2>{}), g),
+ list(f(ct_eq<1>{}), f(ct_eq<2>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::chain(list(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), g),
+ list(f(ct_eq<1>{}), f(ct_eq<2>{}), f(ct_eq<3>{}))
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::chain(list(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}), g),
+ list(f(ct_eq<1>{}), f(ct_eq<2>{}), f(ct_eq<3>{}), f(ct_eq<4>{}))
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // monadic_compose
+ //////////////////////////////////////////////////////////////////
+ {
+ test::_injection<0> f{};
+ test::_injection<1> g{};
+
+ auto mf = [=](auto x) { return list(f(x), f(f(x))); };
+ auto mg = [=](auto x) { return list(g(x), g(g(x))); };
+
+ auto x = test::ct_eq<0>{};
+ BOOST_HANA_CHECK(hana::equal(
+ hana::monadic_compose(mf, mg)(x),
+ list(f(g(x)), f(f(g(x))), f(g(g(x))), f(f(g(g(x)))))
+ ));
+ }
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_MONAD_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/monad_plus.hpp b/src/boost/libs/hana/test/_include/laws/monad_plus.hpp
new file mode 100644
index 000000000..406320c91
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/monad_plus.hpp
@@ -0,0 +1,616 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_MONAD_PLUS_HPP
+#define BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP
+
+#include <boost/hana/append.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/chain.hpp>
+#include <boost/hana/concat.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/monad_plus.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/cycle.hpp>
+#include <boost/hana/empty.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/filter.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/lift.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/prefix.hpp>
+#include <boost/hana/prepend.hpp>
+#include <boost/hana/remove.hpp>
+#include <boost/hana/remove_if.hpp>
+#include <boost/hana/replicate.hpp>
+#include <boost/hana/suffix.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename M, typename = when<true>>
+ struct TestMonadPlus : TestMonadPlus<M, laws> {
+ using TestMonadPlus<M, laws>::TestMonadPlus;
+ };
+
+ template <typename M>
+ struct TestMonadPlus<M, laws> {
+ template <typename Xs, typename Predicates, typename Values>
+ TestMonadPlus(Xs xs, Predicates predicates, Values values) {
+#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
+ empty<M>(); // force adding empty<M>'s member function to pending temploid list
+#endif
+
+ hana::for_each(xs, [](auto a) {
+ static_assert(MonadPlus<decltype(a)>{}, "");
+
+ // left identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::concat(hana::empty<M>(), a),
+ a
+ ));
+
+ // right identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::concat(a, hana::empty<M>()),
+ a
+ ));
+
+ // absorption
+ auto f = hana::compose(lift<M>, test::_injection<0>{});
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(hana::empty<M>(), f),
+ hana::empty<M>()
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::chain(a, hana::always(hana::empty<M>())),
+ hana::empty<M>()
+ ));
+
+ });
+
+ // associativity
+ foreach3(xs, [](auto a, auto b, auto c) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::concat(a, hana::concat(b, c)),
+ hana::concat(hana::concat(a, b), c)
+ ));
+ });
+
+ // Default method definitions
+ hana::for_each(xs, hana::capture(predicates, values)(
+ [](auto predicates, auto values, auto x) {
+
+ // remove_if(x, pred) == filter(x, negated pred)
+ hana::for_each(predicates, hana::capture(x)([](auto x, auto pred) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::remove_if(x, pred),
+ hana::filter(x, hana::compose(hana::not_, pred))
+ ));
+ }));
+
+ // remove(x, value) == remove_if(x, equal.to(value))
+ hana::for_each(values, hana::capture(x)([](auto x, auto value) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::remove(x, value),
+ hana::remove_if(x, hana::equal.to(value))
+ ));
+ }));
+ }));
+ }
+ };
+
+ template <typename S>
+ struct TestMonadPlus<S, when<Sequence<S>::value>>
+ : TestMonadPlus<S, laws>
+ {
+ template <int i>
+ using eq = test::ct_eq<i>;
+
+ struct undefined { };
+
+ template <typename Xs, typename Predicates, typename Values>
+ TestMonadPlus(Xs xs, Predicates predicates, Values values)
+ : TestMonadPlus<S, laws>{xs, predicates, values}
+ {
+ auto z = eq<999>{};
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // empty
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::empty<S>(), list()
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // concat
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(), list()),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(), list(eq<0>{})),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(), list(eq<0>{}, eq<1>{})),
+ list(eq<0>{}, eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}), list()),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}), list(eq<1>{})),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}), list(eq<1>{}, eq<2>{})),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}, eq<1>{}), list()),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}, eq<1>{}), list(eq<2>{})),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(eq<0>{}, eq<1>{}), list(eq<2>{}, eq<3>{})),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
+ ));
+
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ concat(list(), list()),
+ list()
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ concat(list(1), list()),
+ list(1)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ concat(list(), list(1)),
+ list(1)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ concat(list(1), list('2')),
+ list(1, '2')
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ concat(list(1, '2'), list(3.3)),
+ list(1, '2', 3.3)
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // filter
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(), undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(z), not_equal.to(z)),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}), not_equal.to(z)),
+ list(eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, eq<2>{}), not_equal.to(z)),
+ list(eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(z, eq<2>{}), not_equal.to(z)),
+ list(eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, z), not_equal.to(z)),
+ list(eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(z, eq<2>{}, eq<3>{}), not_equal.to(z)),
+ list(eq<2>{}, eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, z, eq<3>{}), not_equal.to(z)),
+ list(eq<1>{}, eq<3>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, eq<2>{}, z), not_equal.to(z)),
+ list(eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, z, z), not_equal.to(z)),
+ list(eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(z, eq<2>{}, z), not_equal.to(z)),
+ list(eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(z, z, eq<3>{}), not_equal.to(z)),
+ list(eq<3>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ filter(list(eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{}, z), not_equal.to(z)),
+ list(eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{})
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // prepend
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prepend(list(), eq<0>{}),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prepend(list(eq<1>{}), eq<0>{}),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prepend(list(eq<1>{}, eq<2>{}), eq<0>{}),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prepend(list(eq<1>{}, eq<2>{}, eq<3>{}), eq<0>{}),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
+ ));
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ prepend(list(), 1),
+ list(1)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ prepend(list('2'), 1),
+ list(1, '2')
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ prepend(list('2', 3.3), 1),
+ list(1, '2', 3.3)
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // append
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ append(list(), eq<0>{}),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ append(list(eq<0>{}), eq<1>{}),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ append(list(eq<0>{}, eq<1>{}), eq<2>{}),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ append(list(), 1), list(1)
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ append(list(1), '2'), list(1, '2')
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(equal(
+ append(list(1, '2'), 3.3), list(1, '2', 3.3)
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // cycle
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(), size_c<0>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(), size_c<1>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(), size_c<2>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(), size_c<3>),
+ list()
+ ));
+
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}), size_c<0>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}), size_c<1>),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}), size_c<2>),
+ list(eq<0>{}, eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}), size_c<3>),
+ list(eq<0>{}, eq<0>{}, eq<0>{})
+ ));
+
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}), size_c<0>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}), size_c<1>),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}), size_c<2>),
+ list(eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}), size_c<3>),
+ list(eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{})
+ ));
+
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<0>),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<1>),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<2>),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<3>),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // remove_if
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(), undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}), equal.to(z)),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z), equal.to(z)),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, eq<1>{}), equal.to(z)),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z, eq<1>{}), equal.to(z)),
+ list(eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, z), equal.to(z)),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z, z), equal.to(z)),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, eq<1>{}, eq<2>{}), equal.to(z)),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, eq<1>{}, z), equal.to(z)),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, z, eq<2>{}), equal.to(z)),
+ list(eq<0>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z, eq<1>{}, eq<2>{}), equal.to(z)),
+ list(eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z, z, eq<2>{}), equal.to(z)),
+ list(eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(eq<0>{}, z, z), equal.to(z)),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ remove_if(list(z, z, z), equal.to(z)),
+ list()
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // remove
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(), undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}), z),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z), z),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, eq<1>{}), z),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z, eq<1>{}), z),
+ list(eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, z), z),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z, z), z),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, eq<1>{}, z), z),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, z, eq<2>{}), z),
+ list(eq<0>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z, eq<1>{}, eq<2>{}), z),
+ list(eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z, z, eq<2>{}), z),
+ list(eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(eq<0>{}, z, z), z),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ hana::remove(list(z, z, z), z),
+ list()
+ ));
+
+ //////////////////////////////////////////////////////////////////
+ // replicate
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<0>),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<1>),
+ list(eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<2>),
+ list(eq<0>{}, eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<3>),
+ list(eq<0>{}, eq<0>{}, eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<4>),
+ list(eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ replicate<S>(eq<0>{}, size_c<5>),
+ list(eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{})
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // prefix
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prefix(list(), z),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prefix(list(eq<0>{}), z),
+ list(z, eq<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prefix(list(eq<0>{}, eq<1>{}), z),
+ list(z, eq<0>{}, z, eq<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prefix(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
+ list(z, eq<0>{}, z, eq<1>{}, z, eq<2>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ prefix(list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}), z),
+ list(z, eq<0>{}, z, eq<1>{}, z, eq<2>{}, z, eq<3>{})
+ ));
+
+
+ //////////////////////////////////////////////////////////////////
+ // suffix
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ suffix(list(), z),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ suffix(list(eq<0>{}), z),
+ list(eq<0>{}, z)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ suffix(list(eq<0>{}, eq<1>{}), z),
+ list(eq<0>{}, z, eq<1>{}, z)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ suffix(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
+ list(eq<0>{}, z, eq<1>{}, z, eq<2>{}, z)
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ suffix(list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}), z),
+ list(eq<0>{}, z, eq<1>{}, z, eq<2>{}, z, eq<3>{}, z)
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/monoid.hpp b/src/boost/libs/hana/test/_include/laws/monoid.hpp
new file mode 100644
index 000000000..d500992a0
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/monoid.hpp
@@ -0,0 +1,86 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_MONOID_HPP
+#define BOOST_HANA_TEST_LAWS_MONOID_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/concept/monoid.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename M, typename = when<true>>
+ struct TestMonoid : TestMonoid<M, laws> {
+ using TestMonoid<M, laws>::TestMonoid;
+ };
+
+ template <typename M>
+ struct TestMonoid<M, laws> {
+ template <typename Xs>
+ TestMonoid(Xs xs) {
+#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
+ zero<M>(); // force adding zero<M>'s member function to pending temploid list
+#endif
+
+ hana::for_each(xs, hana::capture(xs)([](auto xs, auto a) {
+ static_assert(Monoid<decltype(a)>{}, "");
+
+ // left identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(zero<M>(), a),
+ a
+ ));
+
+ // right identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(a, zero<M>()),
+ a
+ ));
+
+ hana::for_each(xs,
+ hana::capture(xs, a)([](auto xs, auto a, auto b) {
+ hana::for_each(xs,
+ hana::capture(a, b)([](auto a, auto b, auto c) {
+ // associativity
+ BOOST_HANA_CHECK(equal(
+ hana::plus(a, hana::plus(b, c)),
+ hana::plus(hana::plus(a, b), c)
+ ));
+ }));
+ }));
+
+ }));
+ }
+ };
+
+ template <typename C>
+ struct TestMonoid<C, when<Constant<C>::value>>
+ : TestMonoid<C, laws>
+ {
+ template <typename Xs>
+ TestMonoid(Xs xs) : TestMonoid<C, laws>{xs} {
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value(zero<C>()),
+ zero<typename C::value_type>()
+ ));
+
+ foreach2(xs, [](auto x, auto y) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::plus(hana::value(x), hana::value(y)),
+ hana::value(hana::plus(x, y))
+ ));
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_MONOID_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/orderable.hpp b/src/boost/libs/hana/test/_include/laws/orderable.hpp
new file mode 100644
index 000000000..f49ea7f8a
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/orderable.hpp
@@ -0,0 +1,182 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_ORDERABLE_HPP
+#define BOOST_HANA_TEST_LAWS_ORDERABLE_HPP
+
+#include <boost/hana/and.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/orderable.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/greater.hpp>
+#include <boost/hana/greater_equal.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/less.hpp>
+#include <boost/hana/less_equal.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/or.hpp>
+#include <boost/hana/ordering.hpp>
+#include <boost/hana/second.hpp>
+#include <boost/hana/value.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename T, typename = when<true>>
+ struct TestOrderable : TestOrderable<T, laws> {
+ using TestOrderable<T, laws>::TestOrderable;
+ };
+
+ template <typename T>
+ struct TestOrderable<T, laws> {
+ template <typename Xs>
+ TestOrderable(Xs xs) {
+ hana::for_each(xs, [](auto x) {
+ static_assert(Orderable<decltype(x)>{}, "");
+ });
+
+ foreach2(xs, [](auto a, auto b) {
+
+ // antisymmetry
+ BOOST_HANA_CHECK(
+ hana::and_(hana::less_equal(a, b), hana::less_equal(b, a))
+ ^implies^ hana::equal(a, b)
+ );
+
+ // totality
+ BOOST_HANA_CHECK(
+ hana::or_(hana::less_equal(a, b), hana::less_equal(b, a))
+ );
+
+ // other methods in terms of `less_equal`
+ BOOST_HANA_CHECK(
+ hana::less(a, b) ^iff^ hana::not_(hana::less_equal(b, a))
+ );
+
+ BOOST_HANA_CHECK(
+ hana::greater(a, b) ^iff^ hana::less(b, a)
+ );
+
+ BOOST_HANA_CHECK(
+ hana::greater_equal(a, b) ^iff^ hana::not_(hana::less(a, b))
+ );
+
+ // less.than & al.
+ BOOST_HANA_CHECK(hana::less.than(a)(b) ^iff^ hana::less(b, a));
+ BOOST_HANA_CHECK(hana::greater.than(a)(b) ^iff^ hana::greater(b, a));
+ BOOST_HANA_CHECK(hana::less_equal.than(a)(b) ^iff^ hana::less_equal(b, a));
+ BOOST_HANA_CHECK(hana::greater_equal.than(a)(b) ^iff^ hana::greater_equal(b, a));
+
+ // ordering
+ _injection<0> f{}; // test::_injection is also monotonic
+ BOOST_HANA_CHECK(
+ hana::ordering(f)(a, b) ^iff^ hana::less(f(a), f(b))
+ );
+ });
+
+ // transitivity
+ foreach3(xs, [](auto a, auto b, auto c) {
+ BOOST_HANA_CHECK(
+ hana::and_(hana::less_equal(a, b), hana::less_equal(b, c))
+ ^implies^ hana::less_equal(a, c)
+ );
+ });
+ }
+ };
+
+ template <typename C>
+ struct TestOrderable<C, when<Constant<C>::value>>
+ : TestOrderable<C, laws>
+ {
+ template <typename Xs>
+ TestOrderable(Xs xs) : TestOrderable<C, laws>{xs} {
+ foreach2(xs, [](auto a, auto b) {
+
+ BOOST_HANA_CHECK(
+ hana::value(hana::less(a, b)) ^iff^
+ hana::less(hana::value(a), hana::value(b))
+ );
+
+ });
+ }
+ };
+
+ template <typename P>
+ struct TestOrderable<P, when<Product<P>::value>>
+ : TestOrderable<P, laws>
+ {
+ template <typename Products>
+ TestOrderable(Products products)
+ : TestOrderable<P, laws>{products}
+ {
+ foreach2(products, [](auto x, auto y) {
+ BOOST_HANA_CHECK(
+ hana::less(x, y) ^iff^
+ hana::or_(
+ hana::less(hana::first(x), hana::first(y)),
+ hana::and_(
+ hana::equal(hana::first(x), hana::first(y)),
+ hana::less(hana::second(x), hana::second(y))
+ )
+ )
+ );
+ });
+ }
+ };
+
+ template <typename S>
+ struct TestOrderable<S, when<Sequence<S>::value>>
+ : TestOrderable<S, laws>
+ {
+ struct invalid { };
+
+ template <typename Xs>
+ TestOrderable(Xs xs) : TestOrderable<S, laws>{xs} {
+ constexpr auto list = make<S>;
+
+ //////////////////////////////////////////////////////////////////
+ // less
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
+ list(),
+ list()
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::less(
+ list(),
+ list(invalid{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
+ list(invalid{}),
+ list()
+ )));
+ BOOST_HANA_CONSTANT_CHECK(hana::less(
+ list(ct_ord<0>{}),
+ list(ct_ord<7>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
+ list(ct_ord<1>{}),
+ list(ct_ord<0>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
+ list(ct_ord<0>{}, ct_ord<1>{}, ct_ord<8>{}),
+ list(ct_ord<0>{}, ct_ord<1>{})
+ )));
+
+ BOOST_HANA_CONSTANT_CHECK(hana::less(
+ list(ct_ord<0>{}, ct_ord<0>{}, ct_ord<8>{}),
+ list(ct_ord<0>{}, ct_ord<1>{})
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_ORDERABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/product.hpp b/src/boost/libs/hana/test/_include/laws/product.hpp
new file mode 100644
index 000000000..18e5a15d2
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/product.hpp
@@ -0,0 +1,46 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_PRODUCT_HPP
+#define BOOST_HANA_TEST_LAWS_PRODUCT_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/concept/product.hpp>
+#include <boost/hana/core/make.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/first.hpp>
+#include <boost/hana/second.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename P, typename = when<true>>
+ struct TestProduct : TestProduct<P, laws> {
+ using TestProduct<P, laws>::TestProduct;
+ };
+
+ template <typename P>
+ struct TestProduct<P, laws> {
+ template <typename Elements>
+ TestProduct(Elements elements) {
+ foreach2(elements, [](auto x, auto y) {
+ static_assert(Product<decltype(hana::make<P>(x, y))>{}, "");
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::first(hana::make<P>(x, y)),
+ x
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::second(hana::make<P>(x, y)),
+ y
+ ));
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_PRODUCT_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/ring.hpp b/src/boost/libs/hana/test/_include/laws/ring.hpp
new file mode 100644
index 000000000..4afbca05c
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/ring.hpp
@@ -0,0 +1,125 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_RING_HPP
+#define BOOST_HANA_TEST_LAWS_RING_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/constant.hpp>
+#include <boost/hana/concept/monoid.hpp>
+#include <boost/hana/concept/ring.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/mult.hpp>
+#include <boost/hana/not_equal.hpp>
+#include <boost/hana/one.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/power.hpp>
+#include <boost/hana/value.hpp>
+
+#include <laws/base.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename R, typename = when<true>>
+ struct TestRing : TestRing<R, laws> {
+ using TestRing<R, laws>::TestRing;
+ };
+
+ template <typename R>
+ struct TestRing<R, laws> {
+ template <typename Xs>
+ TestRing(Xs xs) {
+#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
+ one<R>(); // force adding one<R>'s member function to pending temploid list
+#endif
+
+ hana::for_each(xs, hana::capture(xs)([](auto xs, auto x) {
+ static_assert(Ring<decltype(x)>{}, "");
+
+ foreach2(xs, hana::capture(x)([](auto x, auto y, auto z) {
+ // associativity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(x, hana::mult(y, z)),
+ hana::mult(hana::mult(x, y), z)
+ ));
+
+ // distributivity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(x, hana::plus(y, z)),
+ hana::plus(hana::mult(x, y), hana::mult(x, z))
+ ));
+ }));
+
+ // right identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(x, one<R>()), x
+ ));
+
+ // left identity
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(one<R>(), x), x
+ ));
+
+ // power
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<0>),
+ one<R>()
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<1>),
+ x
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<2>),
+ hana::mult(x, x)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<3>),
+ hana::mult(hana::mult(x, x), x)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<4>),
+ hana::mult(hana::mult(hana::mult(x, x), x), x)
+ ));
+
+ BOOST_HANA_CHECK(hana::equal(
+ hana::power(x, int_c<5>),
+ hana::mult(hana::mult(hana::mult(hana::mult(x, x), x), x), x)
+ ));
+
+ }));
+ }
+ };
+
+ template <typename C>
+ struct TestRing<C, when<Constant<C>::value>>
+ : TestRing<C, laws>
+ {
+ template <typename Xs>
+ TestRing(Xs xs) : TestRing<C, laws>{xs} {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::value(one<C>()),
+ one<typename C::value_type>()
+ ));
+
+ foreach2(xs, [](auto x, auto y) {
+ BOOST_HANA_CHECK(hana::equal(
+ hana::mult(hana::value(x), hana::value(y)),
+ hana::value(hana::mult(x, y))
+ ));
+ });
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_RING_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/searchable.hpp b/src/boost/libs/hana/test/_include/laws/searchable.hpp
new file mode 100644
index 000000000..ae55b06eb
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/searchable.hpp
@@ -0,0 +1,611 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_SEARCHABLE_HPP
+#define BOOST_HANA_TEST_LAWS_SEARCHABLE_HPP
+
+#include <boost/hana/all.hpp>
+#include <boost/hana/all_of.hpp>
+#include <boost/hana/any.hpp>
+#include <boost/hana/any_of.hpp>
+#include <boost/hana/assert.hpp>
+#include <boost/hana/at_key.hpp>
+#include <boost/hana/bool.hpp>
+#include <boost/hana/concat.hpp>
+#include <boost/hana/concept/comparable.hpp>
+#include <boost/hana/concept/searchable.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/contains.hpp>
+#include <boost/hana/core/is_a.hpp>
+#include <boost/hana/core/when.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/find.hpp>
+#include <boost/hana/find_if.hpp>
+#include <boost/hana/for_each.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/is_disjoint.hpp>
+#include <boost/hana/is_subset.hpp>
+#include <boost/hana/lazy.hpp>
+#include <boost/hana/none.hpp>
+#include <boost/hana/none_of.hpp>
+#include <boost/hana/not.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/transform.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <laws/base.hpp>
+#include <support/numeric.hpp>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename S, typename = when<true>>
+ struct TestSearchable : TestSearchable<S, laws> {
+ using TestSearchable<S, laws>::TestSearchable;
+ };
+
+ template <typename S>
+ struct TestSearchable<S, laws> {
+ template <typename Searchables, typename Keys>
+ TestSearchable(Searchables searchables, Keys keys) {
+ hana::for_each(searchables, [](auto xs) {
+ static_assert(Searchable<decltype(xs)>{}, "");
+ });
+
+ auto predicates = hana::concat(
+ hana::to_tuple(hana::transform(keys, equal.to)),
+ hana::make_tuple(
+ hana::always(false_c),
+ hana::always(true_c)
+ )
+ );
+
+ hana::for_each(searchables, hana::capture(searchables, keys, predicates)(
+ [](auto searchables, auto keys, auto predicates, auto xs) {
+ hana::for_each(predicates, hana::capture(xs)(
+ [](auto xs, auto p) {
+ // any_of(xs, p) <=> !all_of(xs, negated p)
+ // <=> !none_of(xs, p)
+ BOOST_HANA_CHECK(
+ hana::any_of(xs, p) ^iff^
+ hana::not_(hana::all_of(xs, hana::compose(not_, p)))
+ );
+
+ BOOST_HANA_CHECK(
+ hana::any_of(xs, p) ^iff^
+ hana::not_(hana::none_of(xs, p))
+ );
+ }));
+
+ // any(xs) <=> any_of(xs, id)
+ // all(xs) <=> all_of(xs, id)
+ // none(xs) <=> none_of(xs, id)
+ auto all_logicals = hana::all_of(xs, [](auto x) {
+ return hana::bool_c<hana::Logical<decltype(x)>::value>;
+ });
+ only_when_(all_logicals, hana::make_lazy([](auto xs) {
+ BOOST_HANA_CHECK(
+ hana::any(xs) ^iff^ hana::any_of(xs, id)
+ );
+
+ BOOST_HANA_CHECK(
+ hana::all(xs) ^iff^ hana::all_of(xs, hana::id)
+ );
+
+ BOOST_HANA_CHECK(
+ hana::none(xs) ^iff^ hana::none_of(xs, hana::id)
+ );
+ })(xs));
+
+ // find_if(xs, always(false_c)) == nothing
+ BOOST_HANA_CONSTANT_CHECK(hana::equal(
+ hana::find_if(xs, hana::always(hana::false_c)),
+ hana::nothing
+ ));
+
+ hana::for_each(searchables, hana::capture(xs)([](auto xs, auto ys) {
+ // is_subset(xs, ys) <=> all_of(xs, [](auto x) { return contains(ys, x); })
+ BOOST_HANA_CHECK(
+ hana::is_subset(xs, ys) ^iff^
+ hana::all_of(xs, hana::partial(hana::contains, ys))
+ );
+
+ // is_disjoint(xs, ys) <=> none_of(xs, [](auto x) { return contains(ys, x); })
+ BOOST_HANA_CHECK(
+ hana::is_disjoint(xs, ys) ^iff^
+ hana::none_of(xs, hana::partial(hana::contains, ys))
+ );
+ }));
+
+ hana::for_each(keys, hana::capture(xs)([](auto xs, auto key) {
+ // find(xs, x) == find_if(xs, [](auto y) { return y == x; })
+ BOOST_HANA_CHECK(hana::equal(
+ hana::find(xs, key),
+ hana::find_if(xs, hana::equal.to(key))
+ ));
+
+ // contains(xs, x) <=> any_of(xs, [](auto y) { return y == x; })
+ BOOST_HANA_CHECK(
+ hana::contains(xs, key) ^iff^
+ hana::any_of(xs, hana::equal.to(key))
+ );
+
+ only_when_(hana::contains(xs, key),
+ hana::make_lazy([](auto xs, auto key) {
+ // at_key(xs, key) == find(xs, key).value()
+ BOOST_HANA_CHECK(hana::equal(
+ hana::at_key(xs, key),
+ hana::find(xs, key).value()
+ ));
+ })(xs, key)
+ );
+ }));
+ }));
+ }
+ };
+
+ template <typename S>
+ struct TestSearchable<S, when<Sequence<S>::value>>
+ : TestSearchable<S, laws>
+ {
+ template <int i>
+ using x = _constant<i>;
+
+ template <int = 0>
+ struct invalid { };
+
+ struct undefined { };
+
+ template <typename Xs, typename Keys>
+ TestSearchable(Xs xs, Keys keys)
+ : TestSearchable<S, laws>{xs, keys}
+ {
+ constexpr auto list = make<S>;
+
+ BOOST_HANA_CONSTEXPR_LAMBDA auto is_even = [](auto x) {
+ return x % 2 == 0;
+ };
+
+ auto c = numeric; // a minimal comparable
+ auto logical = numeric;
+
+ //////////////////////////////////////////////////////////////////
+ // any_of
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(list(), equal.to(x<9>{})))
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(list(x<0>{}), equal.to(x<9>{})))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}), equal.to(x<0>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, invalid<1>{}), equal.to(x<0>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, invalid<1>{}, invalid<2>{}), equal.to(x<0>{}))
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(list(x<0>{}, x<1>{}), equal.to(x<9>{})))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}), equal.to(x<1>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}, invalid<2>{}), equal.to(x<1>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}, invalid<2>{}, invalid<3>{}), equal.to(x<1>{}))
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<9>{})))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<2>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}, x<2>{}, nothing), equal.to(x<2>{}))
+ );
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::any_of(list(x<0>{}, x<1>{}, x<2>{}, nothing, nothing), equal.to(x<2>{}))
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ hana::not_(hana::any_of(list(), invalid<>{}))
+ );
+
+
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::any_of(list(c(0)), equal.to(c(0)))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::not_(hana::any_of(list(c(0)), equal.to(c(1))))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::not_(hana::any_of(list(1), is_even))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::any_of(list(2), is_even)
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::any_of(list(1, 2), is_even)
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::not_(hana::any_of(list(1, 3), is_even))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ hana::any_of(list(1, 3, 4), is_even)
+ );
+
+ //////////////////////////////////////////////////////////////////
+ // any
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any(list())));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::any(list(logical(true))));
+ BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::any(list(logical(false)))));
+
+
+ //////////////////////////////////////////////////////////////////
+ // all_of
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(
+ all_of(list(), invalid<>{})
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ all_of(list(c(0)), equal.to(c(0)))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(
+ not_(all_of(list(c(0)), equal.to(c(1))))
+ );
+ BOOST_HANA_CONSTEXPR_CHECK(not_(
+ all_of(list(c(0), c(1)), equal.to(c(0)))
+ ));
+ BOOST_HANA_CONSTEXPR_CHECK(
+ all_of(list(c(0), c(0)), equal.to(c(0)))
+ );
+
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1), is_even)));
+ BOOST_HANA_CONSTEXPR_CHECK(all_of(list(2), is_even));
+ BOOST_HANA_CONSTEXPR_CHECK(all_of(list(2, 4), is_even));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1, 2), is_even)));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1, 3), is_even)));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1, 3, 4), is_even)));
+
+
+ //////////////////////////////////////////////////////////////////
+ // all
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(all(list()));
+ BOOST_HANA_CONSTEXPR_CHECK(all(list(logical(true))));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all(list(logical(false)))));
+ BOOST_HANA_CONSTEXPR_CHECK(all(list(logical(true), logical(true))));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(all(list(logical(true), logical(false)))));
+
+ //////////////////////////////////////////////////////////////////
+ // none_of
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(none_of(list(), invalid<>{}));
+ BOOST_HANA_CONSTEXPR_CHECK(none_of(list(c(0)), equal.to(c(1))));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(c(0)), equal.to(c(0)))));
+
+ BOOST_HANA_CONSTEXPR_CHECK(none_of(list(1), is_even));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(2), is_even)));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(1, 2), is_even)));
+ BOOST_HANA_CONSTEXPR_CHECK(none_of(list(1, 3), is_even));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(1, 3, 4), is_even)));
+
+
+ //////////////////////////////////////////////////////////////////
+ // none
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(none(list()));
+ BOOST_HANA_CONSTEXPR_CHECK(none(list(logical(false))));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(none(list(logical(true)))));
+
+ //////////////////////////////////////////////////////////////////
+ // find_if
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(), equal.to(x<9>{})),
+ nothing
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}), equal.to(x<9>{})),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}), equal.to(x<0>{})),
+ just(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, invalid<1>{}), equal.to(x<0>{})),
+ just(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, invalid<1>{}, invalid<2>{}), equal.to(x<0>{})),
+ just(x<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}), equal.to(x<9>{})),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}), equal.to(x<1>{})),
+ just(x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, invalid<2>{}), equal.to(x<1>{})),
+ just(x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, invalid<2>{}, invalid<3>{}), equal.to(x<1>{})),
+ just(x<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<9>{})),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<2>{})),
+ just(x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, x<2>{}, nothing), equal.to(x<2>{})),
+ just(x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(list(x<0>{}, x<1>{}, x<2>{}, nothing, nothing), equal.to(x<2>{})),
+ just(x<2>{})
+ ));
+
+ // Make sure find_if works with an lvalue sequence. hana::tuple
+ // used to have a bug that broke this.
+ auto const const_lvalue = list(x<0>{}, x<1>{}, x<2>{});
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(const_lvalue, equal.to(x<1>{})),
+ just(x<1>{})
+ ));
+
+ auto lvalue = list(x<0>{}, x<1>{}, x<2>{});
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find_if(lvalue, equal.to(x<1>{})),
+ just(x<1>{})
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // find
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(), invalid<>{}),
+ nothing
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}), x<9>{}),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}), x<0>{}),
+ just(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, invalid<1>{}), x<0>{}),
+ just(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, invalid<1>{}, invalid<2>{}), x<0>{}),
+ just(x<0>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}), x<9>{}),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}), x<1>{}),
+ just(x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, invalid<2>{}), x<1>{}),
+ just(x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, invalid<2>{}, invalid<3>{}), x<1>{}),
+ just(x<1>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, x<2>{}), x<9>{}),
+ nothing
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, x<2>{}), x<2>{}),
+ just(x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, x<2>{}, nothing), x<2>{}),
+ just(x<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ find(list(x<0>{}, x<1>{}, x<2>{}, nothing, nothing), x<2>{}),
+ just(x<2>{})
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // at_key
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}), x<0>{}),
+ x<0>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}, x<1>{}), x<0>{}),
+ x<0>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}, x<1>{}), x<1>{}),
+ x<1>{}
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}, x<1>{}, x<2>{}), x<0>{}),
+ x<0>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}, x<1>{}, x<2>{}), x<1>{}),
+ x<1>{}
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ at_key(list(x<0>{}, x<1>{}, x<2>{}), x<2>{}),
+ x<2>{}
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // contains
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(not_(
+ contains(list(), undefined{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(not_(
+ contains(list(x<0>{}), x<999>{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(
+ contains(list(x<0>{}), x<0>{})
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ contains(list(x<0>{}, x<1>{}), x<1>{})
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ contains(list(x<0>{}, x<1>{}, x<3>{}), x<3>{})
+ );
+
+ BOOST_HANA_CONSTEXPR_CHECK(contains(list(c(0)), c(0)));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(contains(list(c(0)), c(1))));
+
+ // infix application
+ BOOST_HANA_CONSTANT_CHECK(
+ list(x<0>{}, x<1>{}) ^contains^ x<1>{}
+ );
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // in
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTEXPR_CHECK(c(0) ^in^ list(c(0)));
+ BOOST_HANA_CONSTEXPR_CHECK(not_(c(1) ^in^ list(c(0))));
+
+ //////////////////////////////////////////////////////////////////
+ // is_subset
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(is_subset(
+ list(), list(undefined{})
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(not_(is_subset(
+ list(undefined{}), list()
+ )));
+
+ BOOST_HANA_CONSTEXPR_CHECK(is_subset(
+ list(c(0)), list(c(0))
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(is_subset(
+ list(c(0)), list(c(0), c(1))
+ ));
+
+ BOOST_HANA_CONSTEXPR_CHECK(not_(is_subset(
+ list(c(0)), list(c(1))
+ )));
+
+ // infix application
+ BOOST_HANA_CONSTANT_CHECK(
+ list(x<0>{}) ^is_subset^ list(x<1>{}, x<0>{})
+ );
+
+ BOOST_HANA_CONSTANT_CHECK(
+ list(x<0>{}, x<1>{}) ^is_subset^ list(x<1>{}, x<0>{})
+ );
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // is_disjoint
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(),
+ list(undefined{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(undefined{}),
+ list()
+ ));
+
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(x<0>{}),
+ list(x<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(x<1>{}),
+ list(x<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint(
+ list(x<0>{}),
+ list(x<0>{})
+ )));
+
+
+ BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint(
+ list(x<0>{}, x<1>{}),
+ list(x<0>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint(
+ list(x<0>{}),
+ list(x<0>{}, x<1>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint(
+ list(x<1>{}, x<0>{}),
+ list(x<0>{}, x<1>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint(
+ list(x<0>{}, x<1>{}),
+ list(x<1>{}, x<2>{})
+ )));
+ BOOST_HANA_CONSTANT_CHECK(is_disjoint(
+ list(x<0>{}, x<1>{}),
+ list(x<2>{}, x<3>{})
+ ));
+ }
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_SEARCHABLE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/sequence.hpp b/src/boost/libs/hana/test/_include/laws/sequence.hpp
new file mode 100644
index 000000000..cc04590ea
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/sequence.hpp
@@ -0,0 +1,133 @@
+// Copyright Louis Dionne 2013-2017
+// 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_TEST_LAWS_SEQUENCE_HPP
+#define BOOST_HANA_TEST_LAWS_SEQUENCE_HPP
+
+#include <boost/hana/assert.hpp>
+#include <boost/hana/concept/sequence.hpp>
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/tag_of.hpp>
+#include <boost/hana/functional/capture.hpp>
+#include <boost/hana/functional/compose.hpp>
+#include <boost/hana/functional/id.hpp>
+#include <boost/hana/functional/partial.hpp>
+#include <boost/hana/integral_constant.hpp>
+#include <boost/hana/optional.hpp>
+#include <boost/hana/plus.hpp>
+#include <boost/hana/range.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <laws/base.hpp>
+#include <support/minimal_product.hpp>
+#include <support/seq.hpp>
+
+#include <type_traits>
+#include <vector>
+
+
+namespace boost { namespace hana { namespace test {
+ template <typename S, typename = when<true>>
+ struct TestSequence : TestSequence<S, laws> {
+ using TestSequence<S, laws>::TestSequence;
+ };
+
+ template <typename S>
+ struct TestSequence<S, laws> {
+ template <int i>
+ using eq = integer<i,
+ Policy::Comparable
+ | Policy::Constant
+ >;
+
+ template <int i>
+ using cx_eq = integer<i,
+ Policy::Comparable
+ | Policy::Constexpr
+ >;
+
+ template <int i>
+ using ord = integer<i,
+ Policy::Orderable
+ | Policy::Constant
+ >;
+
+ struct undefined { };
+
+ TestSequence() {
+ constexpr auto list = make<S>; (void)list;
+ constexpr auto foldable = ::seq; (void)foldable;
+
+ //////////////////////////////////////////////////////////////////
+ // Check for Sequence<...>
+ //////////////////////////////////////////////////////////////////
+ static_assert(Sequence<decltype(list())>{}, "");
+ static_assert(Sequence<decltype(list(1))>{}, "");
+ static_assert(Sequence<decltype(list(1, '2'))>{}, "");
+ static_assert(Sequence<decltype(list(1, '2', 3.4))>{}, "");
+
+ //////////////////////////////////////////////////////////////////
+ // Check for basic tag consistency
+ //////////////////////////////////////////////////////////////////
+ struct Random;
+ static_assert(std::is_same<tag_of_t<decltype(list())>, S>{}, "");
+ static_assert(std::is_same<tag_of_t<decltype(list(1))>, S>{}, "");
+ static_assert(std::is_same<tag_of_t<decltype(list(1, '2'))>, S>{}, "");
+ static_assert(std::is_same<tag_of_t<decltype(list(1, '2', 3.3))>, S>{}, "");
+ static_assert(!std::is_same<tag_of_t<Random>, S>{}, "");
+
+ //////////////////////////////////////////////////////////////////
+ // Foldable -> Sequence conversion
+ //////////////////////////////////////////////////////////////////
+ {
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ to<S>(foldable()),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ to<S>(foldable(eq<0>{})),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ to<S>(foldable(eq<0>{}, eq<1>{})),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ to<S>(foldable(eq<0>{}, eq<1>{}, eq<2>{})),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ to<S>(foldable(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
+ ));
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // make (tautological given our definition of `list`)
+ //////////////////////////////////////////////////////////////////
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ make<S>(),
+ list()
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ make<S>(eq<0>{}),
+ list(eq<0>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ make<S>(eq<0>{}, eq<1>{}),
+ list(eq<0>{}, eq<1>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ make<S>(eq<0>{}, eq<1>{}, eq<2>{}),
+ list(eq<0>{}, eq<1>{}, eq<2>{})
+ ));
+ BOOST_HANA_CONSTANT_CHECK(equal(
+ make<S>(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}),
+ list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
+ ));
+ }
+ };
+}}} // end namespace boost::hana::test
+
+#endif // !BOOST_HANA_TEST_LAWS_SEQUENCE_HPP
diff --git a/src/boost/libs/hana/test/_include/laws/templates/seq.hpp b/src/boost/libs/hana/test/_include/laws/templates/seq.hpp
new file mode 100644
index 000000000..72438fc50
--- /dev/null
+++ b/src/boost/libs/hana/test/_include/laws/templates/seq.hpp
@@ -0,0 +1,132 @@
+// Copyright Louis Dionne 2013-2017
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+
+#include <boost/hana/bool.hpp>
+#include <boost/hana/equal.hpp>
+#include <boost/hana/functional/always.hpp>
+#include <boost/hana/tuple.hpp>
+
+#include <laws/applicative.hpp>
+#include <laws/base.hpp>
+#include <laws/comparable.hpp>
+#include <laws/foldable.hpp>
+#include <laws/functor.hpp>
+#include <laws/iterable.hpp>
+#include <laws/monad.hpp>
+#include <laws/monad_plus.hpp>
+#include <laws/orderable.hpp>
+#include <laws/searchable.hpp>
+#include <laws/sequence.hpp>
+#include <support/seq.hpp>
+namespace hana = boost::hana;
+using hana::test::ct_eq;
+using hana::test::ct_ord;
+
+
+int main() {
+ auto eqs = hana::make_tuple(
+ ::seq()
+ , ::seq(ct_eq<0>{})
+ , ::seq(ct_eq<0>{}, ct_eq<1>{})
+ , ::seq(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
+ , ::seq(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
+ );
+ (void)eqs;
+
+ auto nested_eqs = hana::make_tuple(
+ ::seq()
+ , ::seq(
+ ::seq(ct_eq<0>{}))
+ , ::seq(
+ ::seq(ct_eq<0>{}),
+ ::seq(ct_eq<1>{}, ct_eq<2>{}))
+ , ::seq(
+ ::seq(ct_eq<0>{}),
+ ::seq(ct_eq<1>{}, ct_eq<2>{}),
+ ::seq(ct_eq<3>{}, ct_eq<4>{}))
+ );
+ (void)nested_eqs;
+
+ auto eq_keys = hana::make_tuple(ct_eq<0>{}, ct_eq<3>{}, ct_eq<10>{});
+ (void)eq_keys;
+
+ auto predicates = hana::make_tuple(
+ hana::equal.to(ct_eq<0>{}), hana::equal.to(ct_eq<3>{}), hana::equal.to(ct_eq<10>{}),
+ hana::always(hana::true_c), hana::always(hana::false_c)
+ );
+ (void)predicates;
+
+ auto ords = hana::make_tuple(
+ ::seq()
+ , ::seq(ct_ord<0>{})
+ , ::seq(ct_ord<0>{}, ct_ord<1>{})
+ , ::seq(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{})
+ , ::seq(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}, ct_ord<3>{})
+ );
+ (void)ords;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Comparable, Orderable
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_ORDERABLE
+ hana::test::TestComparable<::Seq>{eqs};
+ hana::test::TestOrderable<::Seq>{ords};
+#endif
+
+#ifdef BOOST_HANA_TEST_ITERABLE
+ //////////////////////////////////////////////////////////////////////////
+ // Foldable
+ //////////////////////////////////////////////////////////////////////////
+ hana::test::TestFoldable<::Seq>{eqs};
+
+ //////////////////////////////////////////////////////////////////////////
+ // Iterable
+ //////////////////////////////////////////////////////////////////////////
+ {
+ hana::test::TestIterable<::Seq>{eqs};
+ }
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // Searchable
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_SEARCHABLE
+ {
+ hana::test::TestSearchable<::Seq>{eqs, eq_keys};
+
+ auto bools = hana::make_tuple(
+ ::seq(hana::true_c)
+ , ::seq(hana::false_c)
+ , ::seq(hana::true_c, hana::true_c)
+ , ::seq(hana::true_c, hana::false_c)
+ , ::seq(hana::false_c, hana::true_c)
+ , ::seq(hana::false_c, hana::false_c)
+ );
+ hana::test::TestSearchable<::Seq>{bools, hana::make_tuple(hana::true_c, hana::false_c)};
+ }
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // Functor, Applicative, Monad
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_MONAD
+ hana::test::TestFunctor<::Seq>{eqs, eq_keys};
+ hana::test::TestApplicative<::Seq>{eqs};
+ hana::test::TestMonad<::Seq>{eqs, nested_eqs};
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // MonadPlus
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_MONAD_PLUS
+ hana::test::TestMonadPlus<::Seq>{eqs, predicates, eq_keys};
+#endif
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sequence
+ //////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HANA_TEST_SEQUENCE
+ hana::test::TestSequence<::Seq>{};
+#endif
+}