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)
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 #ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
50 empty<M>(); // force adding empty<M>'s member function to pending temploid list
53 hana::for_each(xs, [](auto a) {
54 static_assert(MonadPlus<decltype(a)>{}, "");
57 BOOST_HANA_CHECK(hana::equal(
58 hana::concat(hana::empty<M>(), a),
63 BOOST_HANA_CHECK(hana::equal(
64 hana::concat(a, hana::empty<M>()),
69 auto f = hana::compose(lift<M>, test::_injection<0>{});
70 BOOST_HANA_CHECK(hana::equal(
71 hana::chain(hana::empty<M>(), f),
75 BOOST_HANA_CHECK(hana::equal(
76 hana::chain(a, hana::always(hana::empty<M>())),
83 foreach3(xs, [](auto a, auto b, auto c) {
84 BOOST_HANA_CHECK(hana::equal(
85 hana::concat(a, hana::concat(b, c)),
86 hana::concat(hana::concat(a, b), c)
90 // Default method definitions
91 hana::for_each(xs, hana::capture(predicates, values)(
92 [](auto predicates, auto values, auto x) {
94 // remove_if(x, pred) == filter(x, negated pred)
95 hana::for_each(predicates, hana::capture(x)([](auto x, auto pred) {
96 BOOST_HANA_CHECK(hana::equal(
97 hana::remove_if(x, pred),
98 hana::filter(x, hana::compose(hana::not_, pred))
102 // remove(x, value) == remove_if(x, equal.to(value))
103 hana::for_each(values, hana::capture(x)([](auto x, auto value) {
104 BOOST_HANA_CHECK(hana::equal(
105 hana::remove(x, value),
106 hana::remove_if(x, hana::equal.to(value))
113 template <typename S>
114 struct TestMonadPlus<S, when<Sequence<S>::value>>
115 : TestMonadPlus<S, laws>
118 using eq = test::ct_eq<i>;
120 struct undefined { };
122 template <typename Xs, typename Predicates, typename Values>
123 TestMonadPlus(Xs xs, Predicates predicates, Values values)
124 : TestMonadPlus<S, laws>{xs, predicates, values}
127 constexpr auto list = make<S>;
129 //////////////////////////////////////////////////////////////////
131 //////////////////////////////////////////////////////////////////
132 BOOST_HANA_CONSTANT_CHECK(equal(
133 hana::empty<S>(), list()
136 //////////////////////////////////////////////////////////////////
138 //////////////////////////////////////////////////////////////////
139 BOOST_HANA_CONSTANT_CHECK(equal(
140 concat(list(), list()),
143 BOOST_HANA_CONSTANT_CHECK(equal(
144 concat(list(), list(eq<0>{})),
147 BOOST_HANA_CONSTANT_CHECK(equal(
148 concat(list(), list(eq<0>{}, eq<1>{})),
149 list(eq<0>{}, eq<1>{})
152 BOOST_HANA_CONSTANT_CHECK(equal(
153 concat(list(eq<0>{}), list()),
156 BOOST_HANA_CONSTANT_CHECK(equal(
157 concat(list(eq<0>{}), list(eq<1>{})),
158 list(eq<0>{}, eq<1>{})
160 BOOST_HANA_CONSTANT_CHECK(equal(
161 concat(list(eq<0>{}), list(eq<1>{}, eq<2>{})),
162 list(eq<0>{}, eq<1>{}, eq<2>{})
165 BOOST_HANA_CONSTANT_CHECK(equal(
166 concat(list(eq<0>{}, eq<1>{}), list()),
167 list(eq<0>{}, eq<1>{})
169 BOOST_HANA_CONSTANT_CHECK(equal(
170 concat(list(eq<0>{}, eq<1>{}), list(eq<2>{})),
171 list(eq<0>{}, eq<1>{}, eq<2>{})
173 BOOST_HANA_CONSTANT_CHECK(equal(
174 concat(list(eq<0>{}, eq<1>{}), list(eq<2>{}, eq<3>{})),
175 list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
179 BOOST_HANA_CONSTANT_CHECK(equal(
180 concat(list(), list()),
183 BOOST_HANA_CONSTEXPR_CHECK(equal(
184 concat(list(1), list()),
187 BOOST_HANA_CONSTEXPR_CHECK(equal(
188 concat(list(), list(1)),
191 BOOST_HANA_CONSTEXPR_CHECK(equal(
192 concat(list(1), list('2')),
195 BOOST_HANA_CONSTEXPR_CHECK(equal(
196 concat(list(1, '2'), list(3.3)),
201 //////////////////////////////////////////////////////////////////
203 //////////////////////////////////////////////////////////////////
204 BOOST_HANA_CONSTANT_CHECK(equal(
205 filter(list(), undefined{}),
209 BOOST_HANA_CONSTANT_CHECK(equal(
210 filter(list(z), not_equal.to(z)),
213 BOOST_HANA_CONSTANT_CHECK(equal(
214 filter(list(eq<1>{}), not_equal.to(z)),
218 BOOST_HANA_CONSTANT_CHECK(equal(
219 filter(list(eq<1>{}, eq<2>{}), not_equal.to(z)),
220 list(eq<1>{}, eq<2>{})
222 BOOST_HANA_CONSTANT_CHECK(equal(
223 filter(list(z, eq<2>{}), not_equal.to(z)),
226 BOOST_HANA_CONSTANT_CHECK(equal(
227 filter(list(eq<1>{}, z), not_equal.to(z)),
231 BOOST_HANA_CONSTANT_CHECK(equal(
232 filter(list(z, eq<2>{}, eq<3>{}), not_equal.to(z)),
233 list(eq<2>{}, eq<3>{})
235 BOOST_HANA_CONSTANT_CHECK(equal(
236 filter(list(eq<1>{}, z, eq<3>{}), not_equal.to(z)),
237 list(eq<1>{}, eq<3>{})
239 BOOST_HANA_CONSTANT_CHECK(equal(
240 filter(list(eq<1>{}, eq<2>{}, z), not_equal.to(z)),
241 list(eq<1>{}, eq<2>{})
243 BOOST_HANA_CONSTANT_CHECK(equal(
244 filter(list(eq<1>{}, z, z), not_equal.to(z)),
247 BOOST_HANA_CONSTANT_CHECK(equal(
248 filter(list(z, eq<2>{}, z), not_equal.to(z)),
251 BOOST_HANA_CONSTANT_CHECK(equal(
252 filter(list(z, z, eq<3>{}), not_equal.to(z)),
256 BOOST_HANA_CONSTANT_CHECK(equal(
257 filter(list(eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{}, z), not_equal.to(z)),
258 list(eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{})
261 //////////////////////////////////////////////////////////////////
263 //////////////////////////////////////////////////////////////////
264 BOOST_HANA_CONSTANT_CHECK(equal(
265 prepend(list(), eq<0>{}),
268 BOOST_HANA_CONSTANT_CHECK(equal(
269 prepend(list(eq<1>{}), eq<0>{}),
270 list(eq<0>{}, eq<1>{})
272 BOOST_HANA_CONSTANT_CHECK(equal(
273 prepend(list(eq<1>{}, eq<2>{}), eq<0>{}),
274 list(eq<0>{}, eq<1>{}, eq<2>{})
276 BOOST_HANA_CONSTANT_CHECK(equal(
277 prepend(list(eq<1>{}, eq<2>{}, eq<3>{}), eq<0>{}),
278 list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})
282 BOOST_HANA_CONSTEXPR_CHECK(equal(
286 BOOST_HANA_CONSTEXPR_CHECK(equal(
287 prepend(list('2'), 1),
290 BOOST_HANA_CONSTEXPR_CHECK(equal(
291 prepend(list('2', 3.3), 1),
295 //////////////////////////////////////////////////////////////////
297 //////////////////////////////////////////////////////////////////
298 BOOST_HANA_CONSTANT_CHECK(equal(
299 append(list(), eq<0>{}),
302 BOOST_HANA_CONSTANT_CHECK(equal(
303 append(list(eq<0>{}), eq<1>{}),
304 list(eq<0>{}, eq<1>{})
306 BOOST_HANA_CONSTANT_CHECK(equal(
307 append(list(eq<0>{}, eq<1>{}), eq<2>{}),
308 list(eq<0>{}, eq<1>{}, eq<2>{})
311 BOOST_HANA_CONSTEXPR_CHECK(equal(
312 append(list(), 1), list(1)
314 BOOST_HANA_CONSTEXPR_CHECK(equal(
315 append(list(1), '2'), list(1, '2')
317 BOOST_HANA_CONSTEXPR_CHECK(equal(
318 append(list(1, '2'), 3.3), list(1, '2', 3.3)
322 //////////////////////////////////////////////////////////////////
324 //////////////////////////////////////////////////////////////////
325 BOOST_HANA_CONSTANT_CHECK(equal(
326 cycle(list(), size_c<0>),
329 BOOST_HANA_CONSTANT_CHECK(equal(
330 cycle(list(), size_c<1>),
333 BOOST_HANA_CONSTANT_CHECK(equal(
334 cycle(list(), size_c<2>),
337 BOOST_HANA_CONSTANT_CHECK(equal(
338 cycle(list(), size_c<3>),
343 BOOST_HANA_CONSTANT_CHECK(equal(
344 cycle(list(eq<0>{}), size_c<0>),
347 BOOST_HANA_CONSTANT_CHECK(equal(
348 cycle(list(eq<0>{}), size_c<1>),
351 BOOST_HANA_CONSTANT_CHECK(equal(
352 cycle(list(eq<0>{}), size_c<2>),
353 list(eq<0>{}, eq<0>{})
355 BOOST_HANA_CONSTANT_CHECK(equal(
356 cycle(list(eq<0>{}), size_c<3>),
357 list(eq<0>{}, eq<0>{}, eq<0>{})
361 BOOST_HANA_CONSTANT_CHECK(equal(
362 cycle(list(eq<0>{}, eq<1>{}), size_c<0>),
365 BOOST_HANA_CONSTANT_CHECK(equal(
366 cycle(list(eq<0>{}, eq<1>{}), size_c<1>),
367 list(eq<0>{}, eq<1>{})
369 BOOST_HANA_CONSTANT_CHECK(equal(
370 cycle(list(eq<0>{}, eq<1>{}), size_c<2>),
371 list(eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{})
373 BOOST_HANA_CONSTANT_CHECK(equal(
374 cycle(list(eq<0>{}, eq<1>{}), size_c<3>),
375 list(eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{})
379 BOOST_HANA_CONSTANT_CHECK(equal(
380 cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<0>),
383 BOOST_HANA_CONSTANT_CHECK(equal(
384 cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<1>),
385 list(eq<0>{}, eq<1>{}, eq<2>{})
387 BOOST_HANA_CONSTANT_CHECK(equal(
388 cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<2>),
389 list(eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{})
391 BOOST_HANA_CONSTANT_CHECK(equal(
392 cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<3>),
393 list(eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{})
396 //////////////////////////////////////////////////////////////////
398 //////////////////////////////////////////////////////////////////
399 BOOST_HANA_CONSTANT_CHECK(equal(
400 remove_if(list(), undefined{}),
404 BOOST_HANA_CONSTANT_CHECK(equal(
405 remove_if(list(eq<0>{}), equal.to(z)),
408 BOOST_HANA_CONSTANT_CHECK(equal(
409 remove_if(list(z), equal.to(z)),
413 BOOST_HANA_CONSTANT_CHECK(equal(
414 remove_if(list(eq<0>{}, eq<1>{}), equal.to(z)),
415 list(eq<0>{}, eq<1>{})
417 BOOST_HANA_CONSTANT_CHECK(equal(
418 remove_if(list(z, eq<1>{}), equal.to(z)),
421 BOOST_HANA_CONSTANT_CHECK(equal(
422 remove_if(list(eq<0>{}, z), equal.to(z)),
425 BOOST_HANA_CONSTANT_CHECK(equal(
426 remove_if(list(z, z), equal.to(z)),
430 BOOST_HANA_CONSTANT_CHECK(equal(
431 remove_if(list(eq<0>{}, eq<1>{}, eq<2>{}), equal.to(z)),
432 list(eq<0>{}, eq<1>{}, eq<2>{})
434 BOOST_HANA_CONSTANT_CHECK(equal(
435 remove_if(list(eq<0>{}, eq<1>{}, z), equal.to(z)),
436 list(eq<0>{}, eq<1>{})
438 BOOST_HANA_CONSTANT_CHECK(equal(
439 remove_if(list(eq<0>{}, z, eq<2>{}), equal.to(z)),
440 list(eq<0>{}, eq<2>{})
442 BOOST_HANA_CONSTANT_CHECK(equal(
443 remove_if(list(z, eq<1>{}, eq<2>{}), equal.to(z)),
444 list(eq<1>{}, eq<2>{})
446 BOOST_HANA_CONSTANT_CHECK(equal(
447 remove_if(list(z, z, eq<2>{}), equal.to(z)),
450 BOOST_HANA_CONSTANT_CHECK(equal(
451 remove_if(list(eq<0>{}, z, z), equal.to(z)),
454 BOOST_HANA_CONSTANT_CHECK(equal(
455 remove_if(list(z, z, z), equal.to(z)),
459 //////////////////////////////////////////////////////////////////
461 //////////////////////////////////////////////////////////////////
462 BOOST_HANA_CONSTANT_CHECK(equal(
463 hana::remove(list(), undefined{}),
467 BOOST_HANA_CONSTANT_CHECK(equal(
468 hana::remove(list(eq<0>{}), z),
471 BOOST_HANA_CONSTANT_CHECK(equal(
472 hana::remove(list(z), z),
476 BOOST_HANA_CONSTANT_CHECK(equal(
477 hana::remove(list(eq<0>{}, eq<1>{}), z),
478 list(eq<0>{}, eq<1>{})
480 BOOST_HANA_CONSTANT_CHECK(equal(
481 hana::remove(list(z, eq<1>{}), z),
484 BOOST_HANA_CONSTANT_CHECK(equal(
485 hana::remove(list(eq<0>{}, z), z),
488 BOOST_HANA_CONSTANT_CHECK(equal(
489 hana::remove(list(z, z), z),
493 BOOST_HANA_CONSTANT_CHECK(equal(
494 hana::remove(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
495 list(eq<0>{}, eq<1>{}, eq<2>{})
497 BOOST_HANA_CONSTANT_CHECK(equal(
498 hana::remove(list(eq<0>{}, eq<1>{}, z), z),
499 list(eq<0>{}, eq<1>{})
501 BOOST_HANA_CONSTANT_CHECK(equal(
502 hana::remove(list(eq<0>{}, z, eq<2>{}), z),
503 list(eq<0>{}, eq<2>{})
505 BOOST_HANA_CONSTANT_CHECK(equal(
506 hana::remove(list(z, eq<1>{}, eq<2>{}), z),
507 list(eq<1>{}, eq<2>{})
509 BOOST_HANA_CONSTANT_CHECK(equal(
510 hana::remove(list(z, z, eq<2>{}), z),
513 BOOST_HANA_CONSTANT_CHECK(equal(
514 hana::remove(list(eq<0>{}, z, z), z),
517 BOOST_HANA_CONSTANT_CHECK(equal(
518 hana::remove(list(z, z, z), z),
522 //////////////////////////////////////////////////////////////////
524 //////////////////////////////////////////////////////////////////
525 BOOST_HANA_CONSTANT_CHECK(equal(
526 replicate<S>(eq<0>{}, size_c<0>),
530 BOOST_HANA_CONSTANT_CHECK(equal(
531 replicate<S>(eq<0>{}, size_c<1>),
535 BOOST_HANA_CONSTANT_CHECK(equal(
536 replicate<S>(eq<0>{}, size_c<2>),
537 list(eq<0>{}, eq<0>{})
540 BOOST_HANA_CONSTANT_CHECK(equal(
541 replicate<S>(eq<0>{}, size_c<3>),
542 list(eq<0>{}, eq<0>{}, eq<0>{})
545 BOOST_HANA_CONSTANT_CHECK(equal(
546 replicate<S>(eq<0>{}, size_c<4>),
547 list(eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{})
550 BOOST_HANA_CONSTANT_CHECK(equal(
551 replicate<S>(eq<0>{}, size_c<5>),
552 list(eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{})
556 //////////////////////////////////////////////////////////////////
558 //////////////////////////////////////////////////////////////////
559 BOOST_HANA_CONSTANT_CHECK(equal(
564 BOOST_HANA_CONSTANT_CHECK(equal(
565 prefix(list(eq<0>{}), z),
569 BOOST_HANA_CONSTANT_CHECK(equal(
570 prefix(list(eq<0>{}, eq<1>{}), z),
571 list(z, eq<0>{}, z, eq<1>{})
574 BOOST_HANA_CONSTANT_CHECK(equal(
575 prefix(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
576 list(z, eq<0>{}, z, eq<1>{}, z, eq<2>{})
579 BOOST_HANA_CONSTANT_CHECK(equal(
580 prefix(list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}), z),
581 list(z, eq<0>{}, z, eq<1>{}, z, eq<2>{}, z, eq<3>{})
585 //////////////////////////////////////////////////////////////////
587 //////////////////////////////////////////////////////////////////
588 BOOST_HANA_CONSTANT_CHECK(equal(
593 BOOST_HANA_CONSTANT_CHECK(equal(
594 suffix(list(eq<0>{}), z),
598 BOOST_HANA_CONSTANT_CHECK(equal(
599 suffix(list(eq<0>{}, eq<1>{}), z),
600 list(eq<0>{}, z, eq<1>{}, z)
603 BOOST_HANA_CONSTANT_CHECK(equal(
604 suffix(list(eq<0>{}, eq<1>{}, eq<2>{}), z),
605 list(eq<0>{}, z, eq<1>{}, z, eq<2>{}, z)
608 BOOST_HANA_CONSTANT_CHECK(equal(
609 suffix(list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}), z),
610 list(eq<0>{}, z, eq<1>{}, z, eq<2>{}, z, eq<3>{}, z)
614 }}} // end namespace boost::hana::test
616 #endif // !BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP