// Copyright Louis Dionne 2013-2016 // 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 #include #include #include #include #include #include #include #include #include #include #include #include namespace hana = boost::hana; using namespace hana::literals; struct Function { }; template struct function_type { using hana_tag = Function; Domain domain_; Codomain codomain_; F f_; template constexpr auto operator()(X x) const { BOOST_HANA_ASSERT(boost::hana::contains(domain_, x)); return f_(x); } }; template constexpr auto operator==(function_type f, function_type g) { return hana::equal(f, g); } template constexpr auto operator!=(function_type f, function_type g) { return hana::not_equal(f, g); } auto function = [](auto domain, auto codomain) { return [=](auto definition) { return function_type{ domain, codomain, definition }; }; }; template constexpr auto domain(Function f) { return f.domain_; } template constexpr auto codomain(Function f) { return f.codomain_; } template constexpr auto range(Function f) { // We must convert to hana::tuple first because hana::set is not a Functor return hana::to_set(hana::transform(hana::to_tuple(domain(f)), f)); } namespace boost { namespace hana { template <> struct equal_impl { template static constexpr auto apply(F f, G g) { return domain(f) == domain(g) && hana::all_of(domain(f), hana::demux(hana::equal)(f, g)); } }; }} // end namespace boost::hana // BOOST_HANA_CONSTEXPR_LAMBDA auto is_injective = [](auto f) { // auto check = [](auto x, auto y) { // return (x != y) ^implies^ (f(x) != f(y)); // }; // return all_of(product(domain(f), domain(f)), check); // }; // BOOST_HANA_CONSTEXPR_LAMBDA auto is_onto = [](auto f) { // return codomain(f) == range(g); // }; ////////////////////////////////////////////////////////////////////////////// int main() { auto f = function(hana::make_set(1_c, 2_c, 3_c), hana::make_set(1_c, 2_c, 3_c, 4_c, 5_c, 6_c))( [](auto x) { return x + 1_c; } ); auto g = function(hana::make_set(1_c, 2_c, 3_c), hana::make_set(2_c, 3_c, 4_c))( [](auto x) { return x + 1_c; } ); auto h = function(hana::make_set(1_c, 2_c, 3_c), hana::make_set(0_c, 1_c, 2_c))( [](auto x) { return x - 1_c; } ); BOOST_HANA_CONSTANT_CHECK(f == g); BOOST_HANA_CONSTANT_CHECK(f != h); BOOST_HANA_CONSTANT_CHECK(f(1_c) == 2_c); BOOST_HANA_CONSTANT_CHECK(range(f) == hana::make_set(4_c, 3_c, 2_c)); }