infinite_set.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // Copyright Louis Dionne 2013-2017
  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. #include <boost/hana/and.hpp>
  5. #include <boost/hana/any_of.hpp>
  6. #include <boost/hana/flatten.hpp>
  7. #include <boost/hana/functional/compose.hpp>
  8. #include <boost/hana/functional/partial.hpp>
  9. #include <boost/hana/fwd/ap.hpp>
  10. #include <boost/hana/fwd/equal.hpp>
  11. #include <boost/hana/fwd/find_if.hpp>
  12. #include <boost/hana/fwd/lift.hpp>
  13. #include <boost/hana/fwd/union.hpp>
  14. #include <boost/hana/if.hpp>
  15. #include <boost/hana/is_subset.hpp>
  16. #include <boost/hana/optional.hpp>
  17. #include <boost/hana/transform.hpp>
  18. namespace hana = boost::hana;
  19. // A `Monad` for searching infinite sets in finite time.
  20. //
  21. // Taken from http://goo.gl/XJeDy8.
  22. struct infinite_set_tag { };
  23. template <typename Find>
  24. struct infinite_set {
  25. Find find;
  26. using hana_tag = infinite_set_tag;
  27. };
  28. template <typename Pred>
  29. constexpr infinite_set<Pred> make_infinite_set(Pred pred) {
  30. return {pred};
  31. }
  32. template <typename X>
  33. constexpr auto singleton(X x) {
  34. return make_infinite_set([=](auto /*p*/) { return x; });
  35. }
  36. template <typename X, typename Y>
  37. constexpr auto doubleton(X x, Y y) {
  38. return make_infinite_set([=](auto p) {
  39. return hana::if_(p(x), x, y);
  40. });
  41. }
  42. namespace boost { namespace hana {
  43. template <>
  44. struct union_impl<infinite_set_tag> {
  45. template <typename Xs, typename Ys>
  46. static constexpr auto apply(Xs xs, Ys ys) {
  47. return flatten(doubleton(xs, ys));
  48. }
  49. };
  50. //////////////////////////////////////////////////////////////////////////
  51. // Comparable
  52. //////////////////////////////////////////////////////////////////////////
  53. template <>
  54. struct equal_impl<infinite_set_tag, infinite_set_tag> {
  55. template <typename Xs, typename Ys>
  56. static constexpr auto apply(Xs xs, Ys ys)
  57. { return and_(is_subset(xs, ys), is_subset(ys, xs)); }
  58. };
  59. //////////////////////////////////////////////////////////////////////////
  60. // Functor
  61. //////////////////////////////////////////////////////////////////////////
  62. template <>
  63. struct transform_impl<infinite_set_tag> {
  64. template <typename Set, typename F>
  65. static constexpr auto apply(Set set, F f) {
  66. return make_infinite_set([=](auto q) {
  67. return f(set.find(compose(q, f)));
  68. });
  69. }
  70. };
  71. //////////////////////////////////////////////////////////////////////////
  72. // Applicative
  73. //////////////////////////////////////////////////////////////////////////
  74. template <>
  75. struct lift_impl<infinite_set_tag> {
  76. template <typename X>
  77. static constexpr auto apply(X x)
  78. { return singleton(x); }
  79. };
  80. template <>
  81. struct ap_impl<infinite_set_tag> {
  82. template <typename F, typename Set>
  83. static constexpr auto apply(F fset, Set set) {
  84. return flatten(transform(fset, partial(transform, set)));
  85. }
  86. };
  87. //////////////////////////////////////////////////////////////////////////
  88. // Monad
  89. //////////////////////////////////////////////////////////////////////////
  90. template <>
  91. struct flatten_impl<infinite_set_tag> {
  92. template <typename Set>
  93. static constexpr auto apply(Set set) {
  94. return make_infinite_set([=](auto p) {
  95. return set.find([=](auto set) {
  96. return any_of(set, p);
  97. }).find(p);
  98. });
  99. }
  100. };
  101. //////////////////////////////////////////////////////////////////////////
  102. // Searchable
  103. //////////////////////////////////////////////////////////////////////////
  104. template <>
  105. struct find_if_impl<infinite_set_tag> {
  106. template <typename Set, typename Pred>
  107. static constexpr auto apply(Set set, Pred p) {
  108. auto x = set.find(p);
  109. return if_(p(x), hana::just(x), hana::nothing);
  110. }
  111. };
  112. template <>
  113. struct any_of_impl<infinite_set_tag> {
  114. template <typename Set, typename Pred>
  115. static constexpr auto apply(Set set, Pred p) {
  116. return p(set.find(p));
  117. }
  118. };
  119. }} // end namespace boost::hana
  120. //////////////////////////////////////////////////////////////////////////////
  121. // Tests
  122. //////////////////////////////////////////////////////////////////////////////
  123. #include <boost/hana/any_of.hpp>
  124. #include <boost/hana/ap.hpp>
  125. #include <boost/hana/assert.hpp>
  126. #include <boost/hana/equal.hpp>
  127. #include <boost/hana/find_if.hpp>
  128. #include <boost/hana/flatten.hpp>
  129. #include <boost/hana/integral_constant.hpp>
  130. #include <boost/hana/is_subset.hpp>
  131. #include <boost/hana/lift.hpp>
  132. #include <boost/hana/not.hpp>
  133. #include <boost/hana/optional.hpp>
  134. #include <boost/hana/plus.hpp>
  135. #include <boost/hana/transform.hpp>
  136. #include <boost/hana/union.hpp>
  137. namespace hana = boost::hana;
  138. template <int i>
  139. constexpr int n = i;
  140. template <int i>
  141. constexpr auto c = hana::int_c<i>;
  142. int main() {
  143. auto f = [](auto n) { return n + hana::int_c<10>; };
  144. auto g = [](auto n) { return n + hana::int_c<100>; };
  145. // union_
  146. {
  147. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  148. hana::union_(singleton(c<0>), singleton(c<0>)),
  149. singleton(c<0>)
  150. ));
  151. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  152. hana::union_(singleton(c<0>), singleton(c<1>)),
  153. doubleton(c<0>, c<1>)
  154. ));
  155. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  156. hana::union_(singleton(c<0>), doubleton(c<0>, c<1>)),
  157. doubleton(c<0>, c<1>)
  158. ));
  159. }
  160. // Comparable
  161. {
  162. // equal
  163. {
  164. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(singleton(n<0>), singleton(n<0>)));
  165. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(singleton(n<0>), singleton(n<1>))));
  166. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(singleton(n<0>), doubleton(n<0>, n<0>)));
  167. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(singleton(n<0>), doubleton(n<0>, n<1>))));
  168. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(singleton(n<0>), doubleton(n<1>, n<1>))));
  169. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(doubleton(n<0>, n<1>), doubleton(n<0>, n<1>)));
  170. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(doubleton(n<0>, n<1>), doubleton(n<1>, n<0>)));
  171. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(doubleton(n<0>, n<1>), doubleton(n<0>, n<0>))));
  172. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(doubleton(n<0>, n<1>), doubleton(n<3>, n<4>))));
  173. }
  174. }
  175. // Functor
  176. {
  177. // transform
  178. {
  179. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  180. hana::transform(singleton(n<0>), f),
  181. singleton(f(n<0>))
  182. ));
  183. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  184. hana::transform(doubleton(n<0>, n<1>), f),
  185. doubleton(f(n<0>), f(n<1>))
  186. ));
  187. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  188. hana::transform(doubleton(n<0>, n<0>), f),
  189. singleton(f(n<0>))
  190. ));
  191. }
  192. }
  193. // Applicative
  194. {
  195. // ap
  196. {
  197. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  198. hana::ap(singleton(f), singleton(c<0>)),
  199. singleton(f(c<0>))
  200. ));
  201. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  202. hana::ap(singleton(f), doubleton(c<0>, c<1>)),
  203. doubleton(f(c<0>), f(c<1>))
  204. ));
  205. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  206. hana::ap(doubleton(f, g), singleton(c<0>)),
  207. doubleton(f(c<0>), g(c<0>))
  208. ));
  209. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  210. hana::ap(doubleton(f, g), doubleton(c<0>, c<1>)),
  211. hana::union_(doubleton(f(c<0>), f(c<1>)),
  212. doubleton(g(c<0>), g(c<1>)))
  213. ));
  214. }
  215. // lift
  216. {
  217. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  218. hana::lift<infinite_set_tag>(c<0>),
  219. singleton(c<0>)
  220. ));
  221. }
  222. }
  223. // Monad
  224. {
  225. // flatten
  226. {
  227. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  228. hana::flatten(singleton(singleton(c<0>))),
  229. singleton(c<0>)
  230. ));
  231. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  232. hana::flatten(singleton(doubleton(c<0>, c<1>))),
  233. doubleton(c<0>, c<1>)
  234. ));
  235. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  236. hana::flatten(doubleton(singleton(c<0>), singleton(c<1>))),
  237. doubleton(c<0>, c<1>)
  238. ));
  239. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  240. hana::flatten(doubleton(doubleton(c<0>, c<1>), singleton(c<2>))),
  241. hana::union_(doubleton(c<0>, c<1>), singleton(c<2>))
  242. ));
  243. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  244. hana::flatten(doubleton(singleton(c<0>), doubleton(c<1>, c<2>))),
  245. hana::union_(doubleton(c<0>, c<1>), singleton(c<2>))
  246. ));
  247. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  248. hana::flatten(doubleton(doubleton(c<0>, c<1>), doubleton(c<2>, c<3>))),
  249. hana::union_(doubleton(c<0>, c<1>), doubleton(c<2>, c<3>))
  250. ));
  251. }
  252. }
  253. // Searchable
  254. {
  255. // any_of
  256. {
  257. BOOST_HANA_CONSTEXPR_CHECK(hana::any_of(singleton(n<0>), hana::equal.to(n<0>)));
  258. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::any_of(singleton(n<0>), hana::equal.to(n<1>))));
  259. BOOST_HANA_CONSTEXPR_CHECK(hana::any_of(doubleton(n<0>, n<1>), hana::equal.to(n<0>)));
  260. BOOST_HANA_CONSTEXPR_CHECK(hana::any_of(doubleton(n<0>, n<1>), hana::equal.to(n<1>)));
  261. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::any_of(doubleton(n<0>, n<1>), hana::equal.to(n<2>))));
  262. }
  263. // find_if
  264. {
  265. BOOST_HANA_CONSTANT_CHECK(hana::find_if(singleton(c<0>), hana::equal.to(c<0>)) == hana::just(c<0>));
  266. BOOST_HANA_CONSTANT_CHECK(hana::find_if(singleton(c<1>), hana::equal.to(c<0>)) == hana::nothing);
  267. BOOST_HANA_CONSTANT_CHECK(hana::find_if(doubleton(c<0>, c<1>), hana::equal.to(c<0>)) == hana::just(c<0>));
  268. BOOST_HANA_CONSTANT_CHECK(hana::find_if(doubleton(c<0>, c<1>), hana::equal.to(c<1>)) == hana::just(c<1>));
  269. BOOST_HANA_CONSTANT_CHECK(hana::find_if(doubleton(c<0>, c<1>), hana::equal.to(c<2>)) == hana::nothing);
  270. }
  271. // is_subset
  272. {
  273. BOOST_HANA_CONSTEXPR_CHECK(hana::is_subset(singleton(n<0>), singleton(n<0>)));
  274. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::is_subset(singleton(n<1>), singleton(n<0>))));
  275. BOOST_HANA_CONSTEXPR_CHECK(hana::is_subset(singleton(n<0>), doubleton(n<0>, n<1>)));
  276. BOOST_HANA_CONSTEXPR_CHECK(hana::is_subset(singleton(n<1>), doubleton(n<0>, n<1>)));
  277. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::is_subset(singleton(n<2>), doubleton(n<0>, n<1>))));
  278. BOOST_HANA_CONSTEXPR_CHECK(hana::is_subset(doubleton(n<0>, n<1>), doubleton(n<0>, n<1>)));
  279. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::is_subset(doubleton(n<0>, n<2>), doubleton(n<0>, n<1>))));
  280. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::is_subset(doubleton(n<2>, n<3>), doubleton(n<0>, n<1>))));
  281. }
  282. }
  283. }