2
0
mirror of https://github.com/boostorg/hana.git synced 2026-02-17 13:52:10 +00:00
Files
hana/test/sandbox/function.cpp
2014-06-23 15:37:29 -04:00

118 lines
3.3 KiB
C++

/*
@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 <boost/hana/comparable.hpp>
#include <boost/hana/core.hpp>
#include <boost/hana/detail/constexpr.hpp>
#include <boost/hana/foldable.hpp>
#include <boost/hana/functional.hpp>
#include <boost/hana/list.hpp>
#include <boost/hana/logical.hpp>
#include <stdexcept>
namespace boost { namespace hana {
struct Function;
template <typename Domain, typename Codomain, typename F, typename = operators::enable>
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 <typename X>
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<decltype(domain), decltype(codomain), decltype(definition)>{
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::instance<Function, Function> : Comparable::equal_mcd {
template <typename F, typename G>
static constexpr auto equal_impl(F f, G g) {
return domain(f) == domain(g) && all(demux(_==_, 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 <boost/hana/detail/static_assert.hpp>
#include <boost/hana/integral.hpp>
#include <boost/hana/list.hpp>
#include <boost/hana/range.hpp>
using namespace boost::hana;
using namespace literals;
int main() {
auto f = function(list_c<int, 1, 2, 3>, list_c<int, 1, 2, 3, 4, 5, 6>)(
[](auto x) {
return x + int_<1>;
}
);
auto g = function(list_c<int, 1, 2, 3>, list_c<int, 2, 3, 4>)(
[](auto x) {
return x + int_<1>;
}
);
auto h = function(list_c<int, 1, 2, 3>, list_c<int, 0, 1, 2>)(
[](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<int, 4, 3, 2>);
}