]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright Louis Dionne 2013-2016 |
2 | // Distributed under the Boost Software License, Version 1.0. | |
3 | // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) | |
4 | ||
5 | #include <boost/hana/all_of.hpp> | |
6 | #include <boost/hana/assert.hpp> | |
7 | #include <boost/hana/contains.hpp> | |
8 | #include <boost/hana/core/to.hpp> | |
9 | #include <boost/hana/equal.hpp> | |
10 | #include <boost/hana/functional/demux.hpp> | |
11 | #include <boost/hana/integral_constant.hpp> | |
12 | #include <boost/hana/minus.hpp> | |
13 | #include <boost/hana/not_equal.hpp> | |
14 | #include <boost/hana/plus.hpp> | |
15 | #include <boost/hana/set.hpp> | |
16 | #include <boost/hana/transform.hpp> | |
17 | #include <boost/hana/tuple.hpp> | |
18 | namespace hana = boost::hana; | |
19 | using namespace hana::literals; | |
20 | ||
21 | ||
22 | struct Function { }; | |
23 | ||
24 | template <typename Domain, typename Codomain, typename F> | |
25 | struct function_type { | |
26 | using hana_tag = Function; | |
27 | ||
28 | Domain domain_; | |
29 | Codomain codomain_; | |
30 | F f_; | |
31 | ||
32 | template <typename X> | |
33 | constexpr auto operator()(X x) const { | |
34 | BOOST_HANA_ASSERT(boost::hana::contains(domain_, x)); | |
35 | return f_(x); | |
36 | } | |
37 | }; | |
38 | ||
39 | template <typename ...F, typename ...G> | |
40 | constexpr auto operator==(function_type<F...> f, function_type<G...> g) | |
41 | { return hana::equal(f, g); } | |
42 | ||
43 | template <typename ...F, typename ...G> | |
44 | constexpr auto operator!=(function_type<F...> f, function_type<G...> g) | |
45 | { return hana::not_equal(f, g); } | |
46 | ||
47 | ||
48 | auto function = [](auto domain, auto codomain) { | |
49 | return [=](auto definition) { | |
50 | return function_type<decltype(domain), decltype(codomain), decltype(definition)>{ | |
51 | domain, codomain, definition | |
52 | }; | |
53 | }; | |
54 | }; | |
55 | ||
56 | template <typename Function> | |
57 | constexpr auto domain(Function f) | |
58 | { return f.domain_; } | |
59 | ||
60 | template <typename Function> | |
61 | constexpr auto codomain(Function f) | |
62 | { return f.codomain_; } | |
63 | ||
64 | template <typename Function> | |
65 | constexpr auto range(Function f) { | |
66 | // We must convert to hana::tuple first because hana::set is not a Functor | |
67 | return hana::to_set(hana::transform(hana::to_tuple(domain(f)), f)); | |
68 | } | |
69 | ||
70 | namespace boost { namespace hana { | |
71 | template <> | |
72 | struct equal_impl<Function, Function> { | |
73 | template <typename F, typename G> | |
74 | static constexpr auto apply(F f, G g) { | |
75 | return domain(f) == domain(g) && | |
76 | hana::all_of(domain(f), hana::demux(hana::equal)(f, g)); | |
77 | } | |
78 | }; | |
79 | }} // end namespace boost::hana | |
80 | ||
81 | ||
82 | // BOOST_HANA_CONSTEXPR_LAMBDA auto is_injective = [](auto f) { | |
83 | // auto check = [](auto x, auto y) { | |
84 | // return (x != y) ^implies^ (f(x) != f(y)); | |
85 | // }; | |
86 | // return all_of(product(domain(f), domain(f)), check); | |
87 | // }; | |
88 | ||
89 | // BOOST_HANA_CONSTEXPR_LAMBDA auto is_onto = [](auto f) { | |
90 | // return codomain(f) == range(g); | |
91 | // }; | |
92 | ||
93 | ////////////////////////////////////////////////////////////////////////////// | |
94 | ||
95 | int main() { | |
96 | 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))( | |
97 | [](auto x) { return x + 1_c; } | |
98 | ); | |
99 | ||
100 | auto g = function(hana::make_set(1_c, 2_c, 3_c), hana::make_set(2_c, 3_c, 4_c))( | |
101 | [](auto x) { return x + 1_c; } | |
102 | ); | |
103 | ||
104 | auto h = function(hana::make_set(1_c, 2_c, 3_c), hana::make_set(0_c, 1_c, 2_c))( | |
105 | [](auto x) { return x - 1_c; } | |
106 | ); | |
107 | ||
108 | BOOST_HANA_CONSTANT_CHECK(f == g); | |
109 | BOOST_HANA_CONSTANT_CHECK(f != h); | |
110 | BOOST_HANA_CONSTANT_CHECK(f(1_c) == 2_c); | |
111 | ||
112 | BOOST_HANA_CONSTANT_CHECK(range(f) == hana::make_set(4_c, 3_c, 2_c)); | |
113 | } |