/* @copyright Louis Dionne 2014 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 namespace boost { namespace hana { struct Function; template struct function_type { using hana_datatype = Function; Domain dom; Codomain cod; F def; friend constexpr auto domain(function_type f) { return f.dom; } friend constexpr auto codomain(function_type f) { return f.cod; } template constexpr auto operator()(X x) const { if (!any(_ == x, domain(*this))) throw std::domain_error{"use of a hana::function with an argument out of the domain"}; return def(x); } }; BOOST_HANA_CONSTEXPR_LAMBDA auto function = [](auto domain, auto codomain) { return [=](auto definition) { return function_type{ domain, codomain, definition }; }; }; BOOST_HANA_CONSTEXPR_LAMBDA auto frange = [](auto f) { // Note: that would be better handled by a set data structure, but // whatever for now. auto insert = [](auto xs, auto x) { return if_(any(_ == x, xs), xs, cons(x, xs)); }; return foldl(insert, list(), fmap(f, domain(f))); }; template <> struct Comparable : defaults { template static constexpr auto equal_impl(F f, G g) { return domain(f) == domain(g) && all(fbind(_==_, f, g), domain(f)); } }; }} // 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(check, product(domain(f), domain(f))); // }; // BOOST_HANA_CONSTEXPR_LAMBDA auto is_onto = [](auto f) { // return codomain(f) == range(g); // }; #include #include #include #include using namespace boost::hana; using namespace literals; int main() { auto f = function(list_c, list_c)( [](auto x) { return x + int_<1>; } ); auto g = function(list_c, list_c)( [](auto x) { return x + int_<1>; } ); auto h = function(list_c, list_c)( [](auto x) { return x - int_<1>; } ); BOOST_HANA_STATIC_ASSERT(f == g); BOOST_HANA_STATIC_ASSERT(f != h); BOOST_HANA_STATIC_ASSERT(f(1) == int_<2>); try { f(6); throw; } catch (std::domain_error) { } BOOST_HANA_STATIC_ASSERT(frange(f) == list_c); }