tree.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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/ap.hpp>
  6. #include <boost/hana/assert.hpp>
  7. #include <boost/hana/concat.hpp>
  8. #include <boost/hana/equal.hpp>
  9. #include <boost/hana/flatten.hpp>
  10. #include <boost/hana/fold_left.hpp>
  11. #include <boost/hana/lift.hpp>
  12. #include <boost/hana/sum.hpp>
  13. #include <boost/hana/transform.hpp>
  14. #include <boost/hana/tuple.hpp>
  15. namespace hana = boost::hana;
  16. struct tree_tag;
  17. template <typename X, typename Subforest>
  18. struct node {
  19. X value;
  20. Subforest subforest;
  21. using hana_tag = tree_tag;
  22. };
  23. constexpr auto make_forest = hana::make_tuple;
  24. template <typename X, typename Subforest>
  25. constexpr auto make_node(X x, Subforest subforest) {
  26. return node<X, Subforest>{x, subforest};
  27. }
  28. namespace boost { namespace hana {
  29. //////////////////////////////////////////////////////////////////////////
  30. // Comparable
  31. //////////////////////////////////////////////////////////////////////////
  32. template <>
  33. struct equal_impl<tree_tag, tree_tag> {
  34. template <typename Node1, typename Node2>
  35. static constexpr auto apply(Node1 node1, Node2 node2) {
  36. return hana::and_(
  37. hana::equal(node1.value, node2.value),
  38. hana::equal(node1.subforest, node2.subforest)
  39. );
  40. }
  41. };
  42. //////////////////////////////////////////////////////////////////////////
  43. // Functor
  44. //////////////////////////////////////////////////////////////////////////
  45. template <>
  46. struct transform_impl<tree_tag> {
  47. template <typename Node, typename F>
  48. static constexpr auto apply(Node node, F f) {
  49. return make_node(
  50. f(node.value),
  51. hana::transform(node.subforest, [=](auto subtree) {
  52. return hana::transform(subtree, f);
  53. })
  54. );
  55. }
  56. };
  57. //////////////////////////////////////////////////////////////////////////
  58. // Applicative
  59. //////////////////////////////////////////////////////////////////////////
  60. template <>
  61. struct lift_impl<tree_tag> {
  62. template <typename X>
  63. static constexpr auto apply(X x)
  64. { return make_node(x, make_forest()); }
  65. };
  66. template <>
  67. struct ap_impl<tree_tag> {
  68. template <typename F, typename X>
  69. static constexpr auto apply(F f, X x) {
  70. return make_node(
  71. f.value(x.value),
  72. hana::concat(
  73. hana::transform(x.subforest, [=](auto subtree) {
  74. return hana::transform(subtree, f.value);
  75. }),
  76. hana::transform(f.subforest, [=](auto subtree) {
  77. return hana::ap(subtree, x);
  78. })
  79. )
  80. );
  81. }
  82. };
  83. //////////////////////////////////////////////////////////////////////////
  84. // Monad
  85. //////////////////////////////////////////////////////////////////////////
  86. template <>
  87. struct flatten_impl<tree_tag> {
  88. template <typename Node>
  89. static constexpr auto apply(Node node) {
  90. return make_node(
  91. node.value.value,
  92. hana::concat(
  93. node.value.subforest,
  94. hana::transform(node.subforest, hana::flatten)
  95. )
  96. );
  97. }
  98. };
  99. //////////////////////////////////////////////////////////////////////////
  100. // Foldable
  101. //////////////////////////////////////////////////////////////////////////
  102. template <>
  103. struct fold_left_impl<tree_tag> {
  104. template <typename Node, typename State, typename F>
  105. static constexpr auto apply(Node node, State state, F f) {
  106. return hana::fold_left(node.subforest, f(state, node.value),
  107. [=](auto state, auto subtree) {
  108. return hana::fold_left(subtree, state, f);
  109. });
  110. }
  111. };
  112. }}
  113. int main() {
  114. constexpr auto tree = make_node(1, make_forest(
  115. make_node(2, make_forest()),
  116. make_node(3, make_forest()),
  117. make_node(4, make_forest())
  118. ));
  119. BOOST_HANA_CONSTEXPR_CHECK(hana::sum<>(tree) == 10);
  120. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  121. hana::transform(tree, [](int i) { return i + 1; }),
  122. make_node(2, make_forest(
  123. make_node(3, make_forest()),
  124. make_node(4, make_forest()),
  125. make_node(5, make_forest())
  126. ))
  127. ));
  128. }