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)
5 #ifndef BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP
6 #define BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP
8 #include <boost/hana/append.hpp>
9 #include <boost/hana/assert.hpp>
10 #include <boost/hana/bool.hpp>
11 #include <boost/hana/chain.hpp>
12 #include <boost/hana/concat.hpp>
13 #include <boost/hana/concept/comparable.hpp>
14 #include <boost/hana/concept/monad_plus.hpp>
15 #include <boost/hana/concept/sequence.hpp>
16 #include <boost/hana/core/make.hpp>
17 #include <boost/hana/core/when.hpp>
18 #include <boost/hana/cycle.hpp>
19 #include <boost/hana/empty.hpp>
20 #include <boost/hana/equal.hpp>
21 #include <boost/hana/filter.hpp>
22 #include <boost/hana/for_each.hpp>
23 #include <boost/hana/functional/capture.hpp>
24 #include <boost/hana/functional/compose.hpp>
25 #include <boost/hana/integral_constant.hpp>
26 #include <boost/hana/lift.hpp>
27 #include <boost/hana/not.hpp>
28 #include <boost/hana/not_equal.hpp>
29 #include <boost/hana/prefix.hpp>
30 #include <boost/hana/prepend.hpp>
31 #include <boost/hana/remove.hpp>
32 #include <boost/hana/remove_if.hpp>
33 #include <boost/hana/replicate.hpp>
34 #include <boost/hana/suffix.hpp>
36 #include <laws/base.hpp>
39 namespace boost { namespace hana { namespace test {
40 template <typename M, typename = when<true>>
41 struct TestMonadPlus : TestMonadPlus<M, laws> {
42 using TestMonadPlus<M, laws>::TestMonadPlus;
46 struct TestMonadPlus<M, laws> {
47 template <typename Xs, typename Predicates, typename Values>
48 TestMonadPlus(Xs xs, Predicates predicates, Values values) {
49 hana::for_each(xs, [](auto a) {
50 static_assert(MonadPlus<decltype(a)>::value, "");
53 BOOST_HANA_CHECK(hana::equal(
54 hana::concat(hana::empty<M>(), a),
59 BOOST_HANA_CHECK(hana::equal(
60 hana::concat(a, hana::empty<M>()),
65 auto f = hana::compose(lift<M>, test::_injection<0>{});
66 BOOST_HANA_CHECK(hana::equal(
67 hana::chain(hana::empty<M>(), f),
71 BOOST_HANA_CHECK(hana::equal(
72 hana::chain(a, hana::always(hana::empty<M>())),
79 foreach3(xs, [](auto a, auto b, auto c) {
80 BOOST_HANA_CHECK(hana::equal(
81 hana::concat(a, hana::concat(b, c)),
82 hana::concat(hana::concat(a, b), c)
86 // Default method definitions
87 hana::for_each(xs, hana::capture(predicates, values)(
88 [](auto predicates, auto values, auto x) {
90 // remove_if(x, pred) == filter(x, negated pred)
91 hana::for_each(predicates, hana::capture(x)([](auto x, auto pred) {
92 BOOST_HANA_CHECK(hana::equal(
93 hana::remove_if(x, pred),
94 hana::filter(x, hana::compose(hana::not_, pred))
98 // remove(x, value) == remove_if(x, equal.to(value))
99 hana::for_each(values, hana::capture(x)([](auto x, auto value) {
100 BOOST_HANA_CHECK(hana::equal(
101 hana::remove(x, value),
102 hana::remove_if(x, hana::equal.to(value))
109 template <typename S>
110 struct TestMonadPlus<S, when<Sequence<S>::value>>
111 : TestMonadPlus<S, laws>
114 using eq = test::ct_eq<i>;
116 struct undefined { };
118 template <typename Xs, typename Predicates, typename Values>
119 TestMonadPlus(Xs xs, Predicates predicates, Values values)
120 : TestMonadPlus<S, laws>{xs, predicates, values}
123 constexpr auto list = make<S>;
125 //////////////////////////////////////////////////////////////////
127 //////////////////////////////////////////////////////////////////
128 BOOST_HANA_CONSTANT_CHECK(equal(
129 hana::empty<S>(), list()
132 //////////////////////////////////////////////////////////////////
134 //////////////////////////////////////////////////////////////////
135 BOOST_HANA_CONSTANT_CHECK(equal(
136 concat(list(), list()),
139 BOOST_HANA_CONSTANT_CHECK(equal(
140 concat(list(), list(eq<0>{})),
143 BOOST_HANA_CONSTANT_CHECK(equal(
144 concat(list(), list(eq<0>{}, eq<1>{})),
145 list(eq<0>{}, eq<1>{})
148 BOOST_HANA_CONSTANT_CHECK(equal(
149 concat(list(eq<0>{}), list()),
152 BOOST_HANA_CONSTANT_CHECK(equal(
153 concat(list(eq<0>{}), list(eq<1>{})),
154 list(eq<0>{}, eq<1>{})
156 BOOST_HANA_CONSTANT_CHECK(equal(
157 concat(list(eq<0>{}), list(eq<1>{}, eq<2>{})),
158 list(eq<0>{}, eq<1>{}, eq<2>{})
161 BOOST_HANA_CONSTANT_CHECK(equal(
162 concat(list(eq<0>{}, eq<1>{}), list()),
163 list(eq<0>{}, eq<1>{})
165 BOOST_HANA_CONSTANT_CHECK(equal(
166 concat(list(eq<0>{}, eq<1>{}), list(eq<2>{})),
167 list(eq<0>{}, eq<1>{}, eq<2>{})
169 BOOST_HANA_CONSTANT_CHECK(equal(
170 concat(list(eq<0>{}, eq<1>{}), list(eq<2>{}, eq<3>{})),
171 list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
175 BOOST_HANA_CONSTANT_CHECK(equal(
176 concat(list(), list()),
179 BOOST_HANA_CONSTEXPR_CHECK(equal(
180 concat(list(1), list()),
183 BOOST_HANA_CONSTEXPR_CHECK(equal(
184 concat(list(), list(1)),
187 BOOST_HANA_CONSTEXPR_CHECK(equal(
188 concat(list(1), list('2')),
191 BOOST_HANA_CONSTEXPR_CHECK(equal(
192 concat(list(1, '2'), list(3.3)),
197 //////////////////////////////////////////////////////////////////
199 //////////////////////////////////////////////////////////////////
200 BOOST_HANA_CONSTANT_CHECK(equal(
201 filter(list(), undefined{}),
205 BOOST_HANA_CONSTANT_CHECK(equal(
206 filter(list(z), not_equal.to(z)),
209 BOOST_HANA_CONSTANT_CHECK(equal(
210 filter(list(eq<1>{}), not_equal.to(z)),
214 BOOST_HANA_CONSTANT_CHECK(equal(
215 filter(list(eq<1>{}, eq<2>{}), not_equal.to(z)),
216 list(eq<1>{}, eq<2>{})
218 BOOST_HANA_CONSTANT_CHECK(equal(
219 filter(list(z, eq<2>{}), not_equal.to(z)),
222 BOOST_HANA_CONSTANT_CHECK(equal(
223 filter(list(eq<1>{}, z), not_equal.to(z)),
227 BOOST_HANA_CONSTANT_CHECK(equal(
228 filter(list(z, eq<2>{}, eq<3>{}), not_equal.to(z)),
229 list(eq<2>{}, eq<3>{})
231 BOOST_HANA_CONSTANT_CHECK(equal(
232 filter(list(eq<1>{}, z, eq<3>{}), not_equal.to(z)),
233 list(eq<1>{}, eq<3>{})
235 BOOST_HANA_CONSTANT_CHECK(equal(
236 filter(list(eq<1>{}, eq<2>{}, z), not_equal.to(z)),
237 list(eq<1>{}, eq<2>{})
239 BOOST_HANA_CONSTANT_CHECK(equal(
240 filter(list(eq<1>{}, z, z), not_equal.to(z)),
243 BOOST_HANA_CONSTANT_CHECK(equal(
244 filter(list(z, eq<2>{}, z), not_equal.to(z)),
247 BOOST_HANA_CONSTANT_CHECK(equal(
248 filter(list(z, z, eq<3>{}), not_equal.to(z)),
252 BOOST_HANA_CONSTANT_CHECK(equal(
253 filter(list(eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{}, z), not_equal.to(z)),
254 list(eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{})
257 //////////////////////////////////////////////////////////////////
259 //////////////////////////////////////////////////////////////////
260 BOOST_HANA_CONSTANT_CHECK(equal(
261 prepend(list(), eq<0>{}),
264 BOOST_HANA_CONSTANT_CHECK(equal(
265 prepend(list(eq<1>{}), eq<0>{}),
266 list(eq<0>{}, eq<1>{})
268 BOOST_HANA_CONSTANT_CHECK(equal(
269 prepend(list(eq<1>{}, eq<2>{}), eq<0>{}),
270 list(eq<0>{}, eq<1>{}, eq<2>{})
272 BOOST_HANA_CONSTANT_CHECK(equal(
273 prepend(list(eq<1>{}, eq<2>{}, eq<3>{}), eq<0>{}),
274 list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
278 BOOST_HANA_CONSTEXPR_CHECK(equal(
282 BOOST_HANA_CONSTEXPR_CHECK(equal(
283 prepend(list('2'), 1),
286 BOOST_HANA_CONSTEXPR_CHECK(equal(
287 prepend(list('2', 3.3), 1),
291 //////////////////////////////////////////////////////////////////
293 //////////////////////////////////////////////////////////////////
294 BOOST_HANA_CONSTANT_CHECK(equal(
295 append(list(), eq<0>{}),
298 BOOST_HANA_CONSTANT_CHECK(equal(
299 append(list(eq<0>{}), eq<1>{}),
300 list(eq<0>{}, eq<1>{})
302 BOOST_HANA_CONSTANT_CHECK(equal(
303 append(list(eq<0>{}, eq<1>{}), eq<2>{}),
304 list(eq<0>{}, eq<1>{}, eq<2>{})
307 BOOST_HANA_CONSTEXPR_CHECK(equal(
308 append(list(), 1), list(1)
310 BOOST_HANA_CONSTEXPR_CHECK(equal(
311 append(list(1), '2'), list(1, '2')
313 BOOST_HANA_CONSTEXPR_CHECK(equal(
314 append(list(1, '2'), 3.3), list(1, '2', 3.3)
318 //////////////////////////////////////////////////////////////////
320 //////////////////////////////////////////////////////////////////
321 BOOST_HANA_CONSTANT_CHECK(equal(
322 cycle(list(), size_c<0>),
325 BOOST_HANA_CONSTANT_CHECK(equal(
326 cycle(list(), size_c<1>),
329 BOOST_HANA_CONSTANT_CHECK(equal(
330 cycle(list(), size_c<2>),
333 BOOST_HANA_CONSTANT_CHECK(equal(
334 cycle(list(), size_c<3>),
339 BOOST_HANA_CONSTANT_CHECK(equal(
340 cycle(list(eq<0>{}), size_c<0>),
343 BOOST_HANA_CONSTANT_CHECK(equal(
344 cycle(list(eq<0>{}), size_c<1>),
347 BOOST_HANA_CONSTANT_CHECK(equal(
348 cycle(list(eq<0>{}), size_c<2>),
349 list(eq<0>{}, eq<0>{})
351 BOOST_HANA_CONSTANT_CHECK(equal(
352 cycle(list(eq<0>{}), size_c<3>),
353 list(eq<0>{}, eq<0>{}, eq<0>{})
357 BOOST_HANA_CONSTANT_CHECK(equal(
358 cycle(list(eq<0>{}, eq<1>{}), size_c<0>),
361 BOOST_HANA_CONSTANT_CHECK(equal(
362 cycle(list(eq<0>{}, eq<1>{}), size_c<1>),
363 list(eq<0>{}, eq<1>{})
365 BOOST_HANA_CONSTANT_CHECK(equal(
366 cycle(list(eq<0>{}, eq<1>{}), size_c<2>),
367 list(eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{})
369 BOOST_HANA_CONSTANT_CHECK(equal(
370 cycle(list(eq<0>{}, eq<1>{}), size_c<3>),
371 list(eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{})
375 BOOST_HANA_CONSTANT_CHECK(equal(
376 cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<0>),
379 BOOST_HANA_CONSTANT_CHECK(equal(
380 cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<1>),
381 list(eq<0>{}, eq<1>{}, eq<2>{})
383 BOOST_HANA_CONSTANT_CHECK(equal(
384 cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<2>),
385 list(eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{})
387 BOOST_HANA_CONSTANT_CHECK(equal(
388 cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<3>),
389 list(eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{})
392 //////////////////////////////////////////////////////////////////
394 //////////////////////////////////////////////////////////////////
395 BOOST_HANA_CONSTANT_CHECK(equal(
396 remove_if(list(), undefined{}),
400 BOOST_HANA_CONSTANT_CHECK(equal(
401 remove_if(list(eq<0>{}), equal.to(z)),
404 BOOST_HANA_CONSTANT_CHECK(equal(
405 remove_if(list(z), equal.to(z)),
409 BOOST_HANA_CONSTANT_CHECK(equal(
410 remove_if(list(eq<0>{}, eq<1>{}), equal.to(z)),
411 list(eq<0>{}, eq<1>{})
413 BOOST_HANA_CONSTANT_CHECK(equal(
414 remove_if(list(z, eq<1>{}), equal.to(z)),
417 BOOST_HANA_CONSTANT_CHECK(equal(
418 remove_if(list(eq<0>{}, z), equal.to(z)),
421 BOOST_HANA_CONSTANT_CHECK(equal(
422 remove_if(list(z, z), equal.to(z)),
426 BOOST_HANA_CONSTANT_CHECK(equal(
427 remove_if(list(eq<0>{}, eq<1>{}, eq<2>{}), equal.to(z)),
428 list(eq<0>{}, eq<1>{}, eq<2>{})
430 BOOST_HANA_CONSTANT_CHECK(equal(
431 remove_if(list(eq<0>{}, eq<1>{}, z), equal.to(z)),
432 list(eq<0>{}, eq<1>{})
434 BOOST_HANA_CONSTANT_CHECK(equal(
435 remove_if(list(eq<0>{}, z, eq<2>{}), equal.to(z)),
436 list(eq<0>{}, eq<2>{})
438 BOOST_HANA_CONSTANT_CHECK(equal(
439 remove_if(list(z, eq<1>{}, eq<2>{}), equal.to(z)),
440 list(eq<1>{}, eq<2>{})
442 BOOST_HANA_CONSTANT_CHECK(equal(
443 remove_if(list(z, z, eq<2>{}), equal.to(z)),
446 BOOST_HANA_CONSTANT_CHECK(equal(
447 remove_if(list(eq<0>{}, z, z), equal.to(z)),
450 BOOST_HANA_CONSTANT_CHECK(equal(
451 remove_if(list(z, z, z), equal.to(z)),
455 //////////////////////////////////////////////////////////////////
457 //////////////////////////////////////////////////////////////////
458 BOOST_HANA_CONSTANT_CHECK(equal(
459 hana::remove(list(), undefined{}),
463 BOOST_HANA_CONSTANT_CHECK(equal(
464 hana::remove(list(eq<0>{}), z),
467 BOOST_HANA_CONSTANT_CHECK(equal(
468 hana::remove(list(z), z),
472 BOOST_HANA_CONSTANT_CHECK(equal(
473 hana::remove(list(eq<0>{}, eq<1>{}), z),
474 list(eq<0>{}, eq<1>{})
476 BOOST_HANA_CONSTANT_CHECK(equal(
477 hana::remove(list(z, eq<1>{}), z),
480 BOOST_HANA_CONSTANT_CHECK(equal(
481 hana::remove(list(eq<0>{}, z), z),
484 BOOST_HANA_CONSTANT_CHECK(equal(
485 hana::remove(list(z, z), z),
489 BOOST_HANA_CONSTANT_CHECK(equal(
490 hana::remove(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
491 list(eq<0>{}, eq<1>{}, eq<2>{})
493 BOOST_HANA_CONSTANT_CHECK(equal(
494 hana::remove(list(eq<0>{}, eq<1>{}, z), z),
495 list(eq<0>{}, eq<1>{})
497 BOOST_HANA_CONSTANT_CHECK(equal(
498 hana::remove(list(eq<0>{}, z, eq<2>{}), z),
499 list(eq<0>{}, eq<2>{})
501 BOOST_HANA_CONSTANT_CHECK(equal(
502 hana::remove(list(z, eq<1>{}, eq<2>{}), z),
503 list(eq<1>{}, eq<2>{})
505 BOOST_HANA_CONSTANT_CHECK(equal(
506 hana::remove(list(z, z, eq<2>{}), z),
509 BOOST_HANA_CONSTANT_CHECK(equal(
510 hana::remove(list(eq<0>{}, z, z), z),
513 BOOST_HANA_CONSTANT_CHECK(equal(
514 hana::remove(list(z, z, z), z),
518 //////////////////////////////////////////////////////////////////
520 //////////////////////////////////////////////////////////////////
521 BOOST_HANA_CONSTANT_CHECK(equal(
522 replicate<S>(eq<0>{}, size_c<0>),
526 BOOST_HANA_CONSTANT_CHECK(equal(
527 replicate<S>(eq<0>{}, size_c<1>),
531 BOOST_HANA_CONSTANT_CHECK(equal(
532 replicate<S>(eq<0>{}, size_c<2>),
533 list(eq<0>{}, eq<0>{})
536 BOOST_HANA_CONSTANT_CHECK(equal(
537 replicate<S>(eq<0>{}, size_c<3>),
538 list(eq<0>{}, eq<0>{}, eq<0>{})
541 BOOST_HANA_CONSTANT_CHECK(equal(
542 replicate<S>(eq<0>{}, size_c<4>),
543 list(eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{})
546 BOOST_HANA_CONSTANT_CHECK(equal(
547 replicate<S>(eq<0>{}, size_c<5>),
548 list(eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{})
552 //////////////////////////////////////////////////////////////////
554 //////////////////////////////////////////////////////////////////
555 BOOST_HANA_CONSTANT_CHECK(equal(
560 BOOST_HANA_CONSTANT_CHECK(equal(
561 prefix(list(eq<0>{}), z),
565 BOOST_HANA_CONSTANT_CHECK(equal(
566 prefix(list(eq<0>{}, eq<1>{}), z),
567 list(z, eq<0>{}, z, eq<1>{})
570 BOOST_HANA_CONSTANT_CHECK(equal(
571 prefix(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
572 list(z, eq<0>{}, z, eq<1>{}, z, eq<2>{})
575 BOOST_HANA_CONSTANT_CHECK(equal(
576 prefix(list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}), z),
577 list(z, eq<0>{}, z, eq<1>{}, z, eq<2>{}, z, eq<3>{})
581 //////////////////////////////////////////////////////////////////
583 //////////////////////////////////////////////////////////////////
584 BOOST_HANA_CONSTANT_CHECK(equal(
589 BOOST_HANA_CONSTANT_CHECK(equal(
590 suffix(list(eq<0>{}), z),
594 BOOST_HANA_CONSTANT_CHECK(equal(
595 suffix(list(eq<0>{}, eq<1>{}), z),
596 list(eq<0>{}, z, eq<1>{}, z)
599 BOOST_HANA_CONSTANT_CHECK(equal(
600 suffix(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
601 list(eq<0>{}, z, eq<1>{}, z, eq<2>{}, z)
604 BOOST_HANA_CONSTANT_CHECK(equal(
605 suffix(list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}), z),
606 list(eq<0>{}, z, eq<1>{}, z, eq<2>{}, z, eq<3>{}, z)
610 }}} // end namespace boost::hana::test
612 #endif // !BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP