// 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace hana { namespace test { template > struct TestApplicative : TestApplicative { using TestApplicative::TestApplicative; }; template struct TestApplicative { template TestApplicative(Applicatives applicatives) { hana::for_each(applicatives, [](auto a) { static_assert(Applicative{}, ""); }); 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(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(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), hana::lift(x)), hana::lift(f(x)) )); } // interchange { hana::for_each(functions1, [](auto fs) { test::ct_eq<4> x{}; BOOST_HANA_CHECK(hana::equal( hana::ap(fs, hana::lift(x)), hana::ap(hana::lift(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), xs) )); }); } } }; template struct TestApplicative::value>> : TestApplicative { template TestApplicative(Applicatives applicatives) : TestApplicative{applicatives} { _injection<0> f{}; _injection<1> g{}; using test::ct_eq; constexpr auto list = make; ////////////////////////////////////////////////////////////////// // 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(ct_eq<0>{}), list(ct_eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(hana::equal( lift(ct_eq<1>{}), list(ct_eq<1>{}) )); } }; }}} // end namespace boost::hana::test #endif // !BOOST_HANA_TEST_LAWS_APPLICATIVE_HPP