1 #pragma once
2 
3 //
4 // fplus.hpp
5 //
6 
7 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
8 // https://github.com/Dobiasd/FunctionalPlus
9 // Distributed under the Boost Software License, Version 1.0.
10 // (See accompanying file LICENSE_1_0.txt or copy at
11 //  http://www.boost.org/LICENSE_1_0.txt)
12 
13 
14 
15 //
16 // compare.hpp
17 //
18 
19 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
20 // https://github.com/Dobiasd/FunctionalPlus
21 // Distributed under the Boost Software License, Version 1.0.
22 // (See accompanying file LICENSE_1_0.txt or copy at
23 //  http://www.boost.org/LICENSE_1_0.txt)
24 
25 
26 
27 //
28 // function_traits.hpp
29 //
30 
31 //--------------------------------------
32 // utils/traits: Additional type traits
33 //--------------------------------------
34 //
35 //          Copyright kennytm (auraHT Ltd.) 2011.
36 // Distributed under the Boost Software License, Version 1.0.
37 //    (See accompanying file LICENSE_1_0.txt or copy at
38 //          http://www.boost.org/LICENSE_1_0.txt)
39 
40 /**
41 
42 ``<utils/traits.hpp>`` --- Additional type traits
43 =================================================
44 
45 This module provides additional type traits and related functions, missing from
46 the standard library.
47 
48 */
49 
50 #ifndef TRAITS_HPP_9ALQFEFX7TO
51 #define TRAITS_HPP_9ALQFEFX7TO 1
52 
53 #include <cstdlib>
54 #include <tuple>
55 #include <functional>
56 #include <type_traits>
57 
58 
59 //
60 // internal/meta.hpp
61 //
62 
63 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
64 // https://github.com/Dobiasd/FunctionalPlus
65 // Distributed under the Boost Software License, Version 1.0.
66 // (See accompanying file LICENSE_1_0.txt or copy at
67 //  http://www.boost.org/LICENSE_1_0.txt)
68 
69 
70 #include <type_traits>
71 
72 namespace fplus
73 {
74 namespace internal
75 {
76 // C++14 compatible void_t (http://en.cppreference.com/w/cpp/types/void_t)
77 template <typename... Ts>
78 struct make_void
79 {
80   using type = void;
81 };
82 
83 template <typename... Ts>
84 using void_t = typename make_void<Ts...>::type;
85 
86 // Sometimes you don't want to use std::decay_t, and the temptation of short
87 // writing can be huge...
88 template <typename T>
89 using uncvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
90 
91 // disjunction/conjunction/negation, useful to short circuit SFINAE checks
92 // Use with parsimony, MSVC 2015 can have ICEs quite easily
93 template <typename...>
94 struct disjunction : std::false_type
95 {
96 };
97 
98 template <typename B1>
99 struct disjunction<B1> : B1
100 {
101 };
102 
103 template <typename B1, typename... Bn>
104 struct disjunction<B1, Bn...>
105     : std::conditional<bool(B1::value), B1, disjunction<Bn...>>::type
106 {
107 };
108 
109 template <typename...>
110 struct conjunction : std::true_type
111 {
112 };
113 
114 template <typename B1>
115 struct conjunction<B1> : B1
116 {
117 };
118 
119 template <typename B1, typename... Bn>
120 struct conjunction<B1, Bn...>
121     : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type
122 {
123 };
124 
125 template <typename B>
126 struct negation : std::integral_constant<bool, !bool(B::value)>
127 {
128 };
129 
130 // non short-circuiting meta functions
131 // source: https://stackoverflow.com/a/27221517/4116453
132 template <bool...>
133 struct bool_pack;
134 
135 template <bool... Values>
136 struct all_of
137     : std::is_same<bool_pack<Values..., true>, bool_pack<true, Values...>>
138 {
139 };
140 
141 // there seems to be a bug in libc++'s std::is_function
142 // provide our own (cppreference one)
143 // (the MSVC implementation seems correct)
144 #ifndef _MSC_VER
145 #define PROVIDE_IS_FUNCTION_POLYFILL
146 #endif
147 
148 #ifndef PROVIDE_IS_FUNCTION_POLYFILL
149 template<class... Any>
150 using is_function = std::is_function<Any...>;
151 #else //PROVIDE_IS_FUNCTION_POLYFILL
152 // primary template
153 template<class>
154 struct is_function : std::false_type { };
155 
156 // specialization for regular functions
157 template<class Ret, class... Args>
158 struct is_function<Ret(Args...)> : std::true_type {};
159 
160 // specialization for variadic functions such as std::printf
161 template<class Ret, class... Args>
162 struct is_function<Ret(Args...,...)> : std::true_type {};
163 
164 // specialization for function types that have cv-qualifiers
165 template<class Ret, class... Args>
166 struct is_function<Ret(Args...) const> : std::true_type {};
167 template<class Ret, class... Args>
168 struct is_function<Ret(Args...) volatile> : std::true_type {};
169 template<class Ret, class... Args>
170 struct is_function<Ret(Args...) const volatile> : std::true_type {};
171 template<class Ret, class... Args>
172 struct is_function<Ret(Args...,...) const> : std::true_type {};
173 template<class Ret, class... Args>
174 struct is_function<Ret(Args...,...) volatile> : std::true_type {};
175 template<class Ret, class... Args>
176 struct is_function<Ret(Args...,...) const volatile> : std::true_type {};
177 
178 // specialization for function types that have ref-qualifiers
179 template<class Ret, class... Args>
180 struct is_function<Ret(Args...) &> : std::true_type {};
181 template<class Ret, class... Args>
182 struct is_function<Ret(Args...) const &> : std::true_type {};
183 template<class Ret, class... Args>
184 struct is_function<Ret(Args...) volatile &> : std::true_type {};
185 template<class Ret, class... Args>
186 struct is_function<Ret(Args...) const volatile &> : std::true_type {};
187 template<class Ret, class... Args>
188 struct is_function<Ret(Args...,...) &> : std::true_type {};
189 template<class Ret, class... Args>
190 struct is_function<Ret(Args...,...) const &> : std::true_type {};
191 template<class Ret, class... Args>
192 struct is_function<Ret(Args...,...) volatile &> : std::true_type {};
193 template<class Ret, class... Args>
194 struct is_function<Ret(Args...,...) const volatile &> : std::true_type {};
195 template<class Ret, class... Args>
196 struct is_function<Ret(Args...) &&> : std::true_type {};
197 template<class Ret, class... Args>
198 struct is_function<Ret(Args...) const &&> : std::true_type {};
199 template<class Ret, class... Args>
200 struct is_function<Ret(Args...) volatile &&> : std::true_type {};
201 template<class Ret, class... Args>
202 struct is_function<Ret(Args...) const volatile &&> : std::true_type {};
203 template<class Ret, class... Args>
204 struct is_function<Ret(Args...,...) &&> : std::true_type {};
205 template<class Ret, class... Args>
206 struct is_function<Ret(Args...,...) const &&> : std::true_type {};
207 template<class Ret, class... Args>
208 struct is_function<Ret(Args...,...) volatile &&> : std::true_type {};
209 template<class Ret, class... Args>
210 struct is_function<Ret(Args...,...) const volatile &&> : std::true_type {};
211 #endif //PROVIDE_IS_FUNCTION_POLYFILL
212 
213 template <typename>
214 struct reverse_integer_sequence_impl;
215 
216 template <typename T>
217 struct reverse_integer_sequence_impl<std::integer_sequence<T>>
218     : std::integer_sequence<T>
219 {
220 };
221 
222 template <typename T, T... Ints>
223 struct reverse_integer_sequence_impl<std::integer_sequence<T, Ints...>>
224     : std::integer_sequence<T, sizeof...(Ints) - 1 - Ints...>
225 {
226 };
227 
228 template <typename Seq>
229 using reverse_integer_sequence = reverse_integer_sequence_impl<Seq>;
230 
231 template <typename T, T N>
232 using make_reverse_integer_sequence =
233     reverse_integer_sequence<std::make_integer_sequence<T, N>>;
234 
235 template <std::size_t... Idx>
236 using reverse_index_sequence =
237     reverse_integer_sequence<std::index_sequence<Idx...>>;
238 
239 template <std::size_t N>
240 using make_reverse_index_sequence =
241     make_reverse_integer_sequence<std::size_t, N>;
242 }
243 }
244 
245 namespace fplus {
246 
247 // source: https://github.com/kennytm/utils
248 namespace utils {
249 
250 #ifdef __GNUC__
251 #pragma GCC diagnostic push
252 #pragma GCC diagnostic ignored "-Weffc++"
253 #endif
254 
255 /**
256 .. macro:: DECLARE_HAS_TYPE_MEMBER(member_name)
257 
258     This macro declares a template ``has_member_name`` which will check whether
259     a type member ``member_name`` exists in a particular type.
260 
261     Example::
262 
263         DECLARE_HAS_TYPE_MEMBER(result_type)
264 
265         ...
266 
267         printf("%d\n", has_result_type< std::plus<int> >::value);
268         // ^ prints '1' (true)
269         printf("%d\n", has_result_type< double(*)() >::value);
270         // ^ prints '0' (false)
271 */
272 #define DECLARE_HAS_TYPE_MEMBER(member_name) \
273     template <typename, typename = void> \
274     struct has_##member_name \
275     { enum { value = false }; }; \
276     template <typename T> \
277     struct has_##member_name<T, typename std::enable_if<sizeof(typename T::member_name)||true>::type> \
278     { enum { value = true }; };
279 
280 /**
281 .. type:: struct utils::function_traits<F>
282 
283     Obtain compile-time information about a function object *F*.
284 
285     This template currently supports the following types:
286 
287     * Normal function types (``R(T...)``), function pointers (``R(*)(T...)``)
288       and function references (``R(&)(T...)`` and ``R(&&)(T...)``).
289     * Member functions (``R(C::*)(T...)``)
290     * ``std::function<F>``
291     * Type of lambda functions, and any other types that has a unique
292       ``operator()``.
293     * Type of ``std::mem_fn`` (only for GCC's libstdc++ and LLVM's libc++).
294       Following the C++ spec, the first argument will be a raw pointer.
295 */
296 template <typename T>
297 struct function_traits
298     : public function_traits<decltype(&T::operator())>
299 {};
300 
301 namespace xx_impl
302 {
303     template <typename C, typename R, typename... A>
304     struct memfn_type
305     {
306         typedef typename std::conditional<
307             std::is_const<C>::value,
308             typename std::conditional<
309                 std::is_volatile<C>::value,
310                 R (C::*)(A...) const volatile,
311                 R (C::*)(A...) const
312             >::type,
313             typename std::conditional<
314                 std::is_volatile<C>::value,
315                 R (C::*)(A...) volatile,
316                 R (C::*)(A...)
317             >::type
318         >::type type;
319     };
320 }
321 
322 template <typename ReturnType, typename... Args>
323 struct function_traits<ReturnType(Args...)>
324 {
325     /**
326     .. type:: type result_type
327 
328         The type returned by calling an instance of the function object type *F*.
329     */
330     typedef ReturnType result_type;
331 
332     /**
333     .. type:: type function_type
334 
335         The function type (``R(T...)``).
336     */
337     typedef ReturnType function_type(Args...);
338 
339     /**
340     .. type:: type member_function_type<OwnerType>
341 
342         The member function type for an *OwnerType* (``R(OwnerType::*)(T...)``).
343     */
344     template <typename OwnerType>
345     using member_function_type = typename xx_impl::memfn_type<
346         typename std::remove_pointer<typename std::remove_reference<OwnerType>::type>::type,
347         ReturnType, Args...
348     >::type;
349 
350     /**
351     .. data:: static const size_t arity
352 
353         Number of arguments the function object will take.
354     */
355     enum { arity = sizeof...(Args) };
356 
357     /**
358     .. type:: type arg<n>::type
359 
360         The type of the *n*-th argument.
361     */
362     template <size_t i>
363     struct arg
364     {
365         typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
366     };
367 };
368 
369 template <typename ReturnType, typename... Args>
370 struct function_traits<ReturnType(*)(Args...)>
371     : public function_traits<ReturnType(Args...)>
372 {};
373 
374 template <typename ClassType, typename ReturnType, typename... Args>
375 struct function_traits<ReturnType(ClassType::*)(Args...)>
376     : public function_traits<ReturnType(Args...)>
377 {
378     typedef ClassType& owner_type;
379 };
380 
381 template <typename ClassType, typename ReturnType, typename... Args>
382 struct function_traits<ReturnType(ClassType::*)(Args...) const>
383     : public function_traits<ReturnType(Args...)>
384 {
385     typedef const ClassType& owner_type;
386 };
387 
388 template <typename ClassType, typename ReturnType, typename... Args>
389 struct function_traits<ReturnType(ClassType::*)(Args...) volatile>
390     : public function_traits<ReturnType(Args...)>
391 {
392     typedef volatile ClassType& owner_type;
393 };
394 
395 template <typename ClassType, typename ReturnType, typename... Args>
396 struct function_traits<ReturnType(ClassType::*)(Args...) const volatile>
397     : public function_traits<ReturnType(Args...)>
398 {
399     typedef const volatile ClassType& owner_type;
400 };
401 
402 template <typename FunctionType>
403 struct function_traits<std::function<FunctionType>>
404     : public function_traits<FunctionType>
405 {};
406 
407 #if defined(_GLIBCXX_FUNCTIONAL)
408 #define MEM_FN_SYMBOL_XX0SL7G4Z0J std::_Mem_fn
409 #elif defined(_LIBCPP_FUNCTIONAL)
410 #define MEM_FN_SYMBOL_XX0SL7G4Z0J std::__mem_fn
411 #endif
412 
413 #ifdef MEM_FN_SYMBOL_XX0SL7G4Z0J
414 
415 template <typename R, typename C>
416 struct function_traits<MEM_FN_SYMBOL_XX0SL7G4Z0J<R C::*>>
417     : public function_traits<R(C*)>
418 {};
419 template <typename R, typename C, typename... A>
420 struct function_traits<MEM_FN_SYMBOL_XX0SL7G4Z0J<R(C::*)(A...)>>
421     : public function_traits<R(C*, A...)>
422 {};
423 template <typename R, typename C, typename... A>
424 struct function_traits<MEM_FN_SYMBOL_XX0SL7G4Z0J<R(C::*)(A...) const>>
425     : public function_traits<R(const C*, A...)>
426 {};
427 template <typename R, typename C, typename... A>
428 struct function_traits<MEM_FN_SYMBOL_XX0SL7G4Z0J<R(C::*)(A...) volatile>>
429     : public function_traits<R(volatile C*, A...)>
430 {};
431 template <typename R, typename C, typename... A>
432 struct function_traits<MEM_FN_SYMBOL_XX0SL7G4Z0J<R(C::*)(A...) const volatile>>
433     : public function_traits<R(const volatile C*, A...)>
434 {};
435 
436 #undef MEM_FN_SYMBOL_XX0SL7G4Z0J
437 #endif
438 
439 template <typename T>
440 struct function_traits<T&> : public function_traits<T> {};
441 template <typename T>
442 struct function_traits<const T&> : public function_traits<T> {};
443 template <typename T>
444 struct function_traits<volatile T&> : public function_traits<T> {};
445 template <typename T>
446 struct function_traits<const volatile T&> : public function_traits<T> {};
447 template <typename T>
448 struct function_traits<T&&> : public function_traits<T> {};
449 template <typename T>
450 struct function_traits<const T&&> : public function_traits<T> {};
451 template <typename T>
452 struct function_traits<volatile T&&> : public function_traits<T> {};
453 template <typename T>
454 struct function_traits<const volatile T&&> : public function_traits<T> {};
455 
456 
457 #define FORWARD_RES_8QR485JMSBT \
458     typename std::conditional< \
459         std::is_lvalue_reference<R>::value, \
460         T&, \
461         typename std::remove_reference<T>::type&& \
462     >::type
463 
464 /**
465 .. function:: auto utils::forward_like<Like, T>(T&& t) noexcept
466 
467     Forward the reference *t* like the type of *Like*. That means, if *Like* is
468     an lvalue (reference), this function will return an lvalue reference of *t*.
469     Otherwise, if *Like* is an rvalue, this function will return an rvalue
470     reference of *t*.
471 
472     This is mainly used to propagate the expression category (lvalue/rvalue) of
473     a member of *Like*, generalizing ``std::forward``.
474 */
475 template <typename R, typename T>
forward_like(T && input)476 FORWARD_RES_8QR485JMSBT forward_like(T&& input) noexcept
477 {
478     return static_cast<FORWARD_RES_8QR485JMSBT>(input);
479 }
480 
481 #undef FORWARD_RES_8QR485JMSBT
482 
483 /**
484 .. type:: struct utils::copy_cv<From, To>
485 
486     Copy the CV qualifier between the two types. For example,
487     ``utils::copy_cv<const int, double>::type`` will become ``const double``.
488 */
489 template <typename From, typename To>
490 struct copy_cv
491 {
492 private:
493     typedef typename std::remove_cv<To>::type raw_To;
494     typedef typename std::conditional<std::is_const<From>::value,
495                                       const raw_To, raw_To>::type const_raw_To;
496 public:
497     /**
498     .. type:: type type
499 
500         Result of cv-copying.
501     */
502     typedef typename std::conditional<std::is_volatile<From>::value,
503                                       volatile const_raw_To, const_raw_To>::type type;
504 };
505 
506 /**
507 .. type:: struct utils::pointee<T>
508 
509     Returns the type by derefering an instance of *T*. This is a generalization
510     of ``std::remove_pointer``, that it also works with iterators.
511 */
512 template <typename T>
513 struct pointee
514 {
515     /**
516     .. type:: type type
517 
518         Result of dereferencing.
519     */
520     typedef typename std::remove_reference<decltype(*std::declval<T>())>::type type;
521 };
522 
523 /**
524 .. function:: std::add_rvalue_reference<T>::type utils::rt_val<T>() noexcept
525 
526     Returns a value of type *T*. It is guaranteed to do nothing and will not
527     throw a compile-time error, but using the returned result will cause
528     undefined behavior.
529 */
530 template <typename T>
rt_val()531 typename std::add_rvalue_reference<T>::type rt_val() noexcept
532 {
533     return std::move(*static_cast<T*>(nullptr));
534 }
535 
536 #ifdef __GNUC__
537 #pragma GCC diagnostic pop
538 #endif
539 
540 }
541 }
542 
543 namespace fplus
544 {
545 namespace internal
546 {
547 template <typename>
548 struct is_std_function : std::false_type
549 {
550 };
551 
552 template <typename T>
553 struct is_std_function<std::function<T>> : std::true_type
554 {
555 };
556 
557 // Those traits are needed to not perform arity checks on a generic-lambd
558 // or a templated/overloaded operator()
559 template <typename T, typename = void>
560 struct has_function_traits : std::false_type
561 {
562 };
563 
564 // There is a bug with GCC 7 when a std::function is passed as T.
565 // It produces an ambiguous call between this one and the std::function overload
566 // It's related to our void_t implementation, the C++14 compatible version does not
567 // work, whereas the C++17 one does...
568 //
569 // So, help GCC a bit with is_std_function
570 template <typename T>
571 struct has_function_traits<T,
572                            std::enable_if_t<!is_std_function<T>::value,
573                                             void_t<decltype(&T::operator())>>>
574     : std::true_type
575 {
576 };
577 
578 template <typename ReturnType, typename... Args>
579 struct has_function_traits<ReturnType(Args...)> : std::true_type
580 {
581 };
582 
583 template <typename ReturnType, typename... Args>
584 struct has_function_traits<ReturnType (*)(Args...)> : std::true_type
585 {
586 };
587 
588 template <typename ReturnType, typename ClassType, typename... Args>
589 struct has_function_traits<ReturnType (ClassType::*)(Args...)> : std::true_type
590 {
591 };
592 
593 template <typename ReturnType, typename ClassType, typename... Args>
594 struct has_function_traits<ReturnType (ClassType::*)(Args...) const>
595     : std::true_type
596 {
597 };
598 
599 template <typename ReturnType, typename ClassType, typename... Args>
600 struct has_function_traits<ReturnType (ClassType::*)(Args...) volatile>
601     : std::true_type
602 {
603 };
604 
605 template <typename ReturnType, typename ClassType, typename... Args>
606 struct has_function_traits<ReturnType (ClassType::*)(Args...) const volatile>
607     : std::true_type
608 {
609 };
610 
611 template <typename ReturnType, typename ClassType, typename... Args>
612 struct has_function_traits<ReturnType (ClassType::*)(Args...)&> : std::true_type
613 {
614 };
615 
616 template <typename ReturnType, typename ClassType, typename... Args>
617 struct has_function_traits<ReturnType (ClassType::*)(Args...) const &>
618     : std::true_type
619 {
620 };
621 
622 template <typename ReturnType, typename ClassType, typename... Args>
623 struct has_function_traits<ReturnType (ClassType::*)(Args...) volatile&>
624     : std::true_type
625 {
626 };
627 
628 template <typename ReturnType, typename ClassType, typename... Args>
629 struct has_function_traits<ReturnType (ClassType::*)(Args...) const volatile&>
630     : std::true_type
631 {
632 };
633 
634 template <typename ReturnType, typename ClassType, typename... Args>
635 struct has_function_traits<ReturnType (ClassType::*)(Args...) &&>
636     : std::true_type
637 {
638 };
639 
640 template <typename ReturnType, typename ClassType, typename... Args>
641 struct has_function_traits<ReturnType (ClassType::*)(Args...) const &&>
642     : std::true_type
643 {
644 };
645 
646 template <typename ReturnType, typename ClassType, typename... Args>
647 struct has_function_traits<ReturnType (ClassType::*)(Args...) volatile&&>
648     : std::true_type
649 {
650 };
651 
652 template <typename ReturnType, typename ClassType, typename... Args>
653 struct has_function_traits<ReturnType (ClassType::*)(Args...) const volatile&&>
654     : std::true_type
655 {
656 };
657 
658 template <typename FunctionType>
659 struct has_function_traits<std::function<FunctionType>> : std::true_type
660 {
661 };
662 }
663 }
664 
665 #endif
666 
667 //
668 // composition.hpp
669 //
670 
671 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
672 // https://github.com/Dobiasd/FunctionalPlus
673 // Distributed under the Boost Software License, Version 1.0.
674 // (See accompanying file LICENSE_1_0.txt or copy at
675 //  http://www.boost.org/LICENSE_1_0.txt)
676 
677 
678 
679 //
680 // internal/apply.hpp
681 //
682 
683 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
684 // https://github.com/Dobiasd/FunctionalPlus
685 // Distributed under the Boost Software License, Version 1.0.
686 // (See accompanying file LICENSE_1_0.txt or copy at
687 //  http://www.boost.org/LICENSE_1_0.txt)
688 
689 
690 #include <tuple>
691 #include <type_traits>
692 #include <utility>
693 
694 
695 //
696 // internal/invoke.hpp
697 //
698 
699 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
700 // https://github.com/Dobiasd/FunctionalPlus
701 // Distributed under the Boost Software License, Version 1.0.
702 // (See accompanying file LICENSE_1_0.txt or copy at
703 //  http://www.boost.org/LICENSE_1_0.txt)
704 
705 
706 #include <functional>
707 #include <type_traits>
708 #include <utility>
709 
710 
711 // borrowed to libc++
712 #define FPLUS_INVOKE_RETURN(...) \
713   ->decltype(__VA_ARGS__)        \
714   {                              \
715     return __VA_ARGS__;          \
716   }
717 
718 namespace fplus
719 {
720 namespace internal
721 {
722 // We need std::invoke to detect callable objects
723 //
724 // source:
725 // http://en.cppreference.com/mwiki/index.php?title=cpp/utility/functional/invoke&oldid=82514
726 template <typename U>
727 static std::true_type is_refwrap_test(const std::reference_wrapper<U>&);
728 
729 template <typename U>
730 static std::false_type is_refwrap_test(const U&);
731 
732 template <typename T>
733 struct is_reference_wrapper : decltype(is_refwrap_test(std::declval<T>()))
734 {
735 };
736 
737 template <typename T, typename U = typename std::decay<T>::type>
738 struct unwrap_reference_wrapper
739 {
740   using type = T;
741 };
742 
743 template <typename T, typename U>
744 struct unwrap_reference_wrapper<T, std::reference_wrapper<U>>
745 {
746   using type = U&;
747 };
748 
749 template <typename T>
750 using unwrap_reference_wrapper_t = typename unwrap_reference_wrapper<T>::type;
751 
752 // note: clang only triggers the second static_assert
753 //      - static_assert(is_invocable<&base_class::non_const_method, const derived_class&>::value, "");
754 //      - static_assert(is_invocable<&base_class::non_const_method, const base_class&>::value, "");
755 // GCC triggers both. To workaround this clang bug, we have to manage cv correctness ourselves
756 
757 template <typename T>
758 struct is_const_member_function : std::false_type
759 {
760 };
761 
762 // decay doesn't add pointer to abominable functions, don't bother writing them
763 template <typename R, typename... Args>
764 struct is_const_member_function<R(Args...) const> : std::true_type
765 {
766 };
767 
768 template <typename R, typename... Args>
769 struct is_const_member_function<R(Args...) const&> : std::true_type
770 {
771 };
772 
773 template <typename R, typename... Args>
774 struct is_const_member_function<R(Args...) const&&> : std::true_type
775 {
776 };
777 
778 template <typename R, typename... Args>
779 struct is_const_member_function<R(Args...) const volatile> : std::true_type
780 {
781 };
782 
783 template <typename R, typename... Args>
784 struct is_const_member_function<R(Args...) const volatile&> : std::true_type
785 {
786 };
787 
788 template <typename R, typename... Args>
789 struct is_const_member_function<R(Args...) const volatile&&> : std::true_type
790 {
791 };
792 
793 template <typename T>
794 struct is_volatile_member_function : std::false_type
795 {
796 };
797 
798 // decay doesn't add pointer to abominable functions, don't bother writing them
799 template <typename R, typename... Args>
800 struct is_volatile_member_function<R(Args...) volatile> : std::true_type
801 {
802 };
803 
804 template <typename R, typename... Args>
805 struct is_volatile_member_function<R(Args...) volatile&> : std::true_type
806 {
807 };
808 
809 template <typename R, typename... Args>
810 struct is_volatile_member_function<R(Args...) volatile&&> : std::true_type
811 {
812 };
813 
814 template <typename R, typename... Args>
815 struct is_volatile_member_function<R(Args...) const volatile> : std::true_type
816 {
817 };
818 
819 template <typename R, typename... Args>
820 struct is_volatile_member_function<R(Args...) const volatile&> : std::true_type
821 {
822 };
823 
824 template <typename R, typename... Args>
825 struct is_volatile_member_function<R(Args...) const volatile&&> : std::true_type
826 {
827 };
828 
829 template <typename Object, typename Signature>
830 struct has_correct_cv
831 {
832   // if object has no cv, every method can be called
833   // else the method must have the same cv than the object
834   static constexpr bool value =
835       std::is_same<typename std::remove_cv<Object>::type, Object>::value ||
836       ((is_volatile_member_function<Signature>::value ==
837         std::is_volatile<Object>::value) &&
838        (is_const_member_function<Signature>::value ==
839         std::is_const<Object>::value));
840 };
841 
842 // pointer to member function - reference to object
843 template <
844     typename Base,
845     typename T,
846     typename Derived,
847     typename... Args,
848     typename Unwrapped = unwrap_reference_wrapper_t<Derived>,
849     typename std::enable_if<
850         is_function<T>::value &&
851             has_correct_cv<typename std::remove_reference<Unwrapped>::type, T>::value &&
852             std::is_base_of<Base, typename std::decay<Unwrapped>::type>::value,
853         int>::type = 0>
854 inline auto invoke_impl(T Base::*pmf, Derived&& ref, Args&&... args)
855     FPLUS_INVOKE_RETURN((std::forward<Unwrapped>(ref).*
856                          pmf)(std::forward<Args>(args)...))
857 
858 // pointer to member function - pointer to object
859 template <
860     typename Base,
861     typename T,
862     typename Pointer,
863     typename... Args,
864     typename std::enable_if<
865         is_function<T>::value &&
866             has_correct_cv<typename std::remove_pointer<
867                                typename std::decay<Pointer>::type>::type,
868                            T>::value &&
869             !std::is_base_of<Base, typename std::decay<Pointer>::type>::value,
870         int>::type = 0>
871 inline auto invoke_impl(T Base::*pmf, Pointer&& ptr, Args&&... args)
872     FPLUS_INVOKE_RETURN(((*std::forward<Pointer>(ptr)).*
873                          pmf)(std::forward<Args>(args)...))
874 
875 // pointer to non-static data member - reference to object
876 template <
877     typename Base,
878     typename T,
879     typename Derived,
880     typename Unwrapped = unwrap_reference_wrapper_t<Derived>,
881     typename std::enable_if<
882         !is_function<T>::value &&
883             std::is_base_of<Base, typename std::decay<Unwrapped>::type>::value,
884         int>::type = 0>
885 inline auto invoke_impl(T Base::*pmd, Derived&& ref)
886     FPLUS_INVOKE_RETURN((std::forward<Unwrapped>(ref).*pmd))
887 
888 // pointer to non-static data member - pointer to object
889 template <
890     typename Base,
891     typename T,
892     typename Pointer,
893     typename std::enable_if<
894         !is_function<T>::value &&
895             !std::is_base_of<Base, typename std::decay<Pointer>::type>::value,
896         int>::type = 0>
897 inline auto invoke_impl(T Base::*pmd, Pointer&& ptr)
898     FPLUS_INVOKE_RETURN((*std::forward<Pointer>(ptr)).*pmd)
899 
900 // normal case - functions, lambdas, function objects
901 template <typename F,
902           typename... Args,
903           typename std::enable_if<
904               !std::is_member_pointer<typename std::decay<F>::type>::value,
905               int>::type = 0>
906 inline auto invoke_impl(F&& f, Args&&... args)
907     FPLUS_INVOKE_RETURN((std::forward<F>(f)(std::forward<Args>(args)...)))
908 
909 template <typename AlwaysVoid, typename, typename...>
910 struct invoke_result_impl
911 {
912 };
913 
914 template <typename F, typename... Args>
915 struct invoke_result_impl<decltype(void(invoke_impl(std::declval<F>(),
916                                                     std::declval<Args>()...))),
917                           F,
918                           Args...>
919 {
920   using type =
921       decltype(invoke_impl(std::declval<F>(), std::declval<Args>()...));
922 };
923 
924 template <typename F, typename... ArgTypes>
925 struct invoke_result : invoke_result_impl<void, F, ArgTypes...>
926 {
927 };
928 
929 template <typename F, typename... Args>
930 using invoke_result_t = typename invoke_result<F, Args...>::type;
931 
932 // noexcept omitted on purpose, cannot be implemented without C++17.
933 // GCC 7.1 works with libstdc++, but clang fails, even with latest build,
934 // on both libstdc++/libc++, I suspect an internal compiler trait is at
935 // play to make GCC work.
936 //
937 // We could detect if C++17 is used and use std::invoke directly.
938 template <typename F, typename... ArgTypes>
invoke(F && f,ArgTypes &&...args)939 invoke_result_t<F, ArgTypes...> invoke(F&& f, ArgTypes&&... args)
940 {
941   return invoke_impl(std::forward<F>(f), std::forward<ArgTypes>(args)...);
942 }
943 
944 // Invoke useful traits (libstdc++ 7.1.0's implementation, ugly-case removed)
945 template <typename Result, typename ReturnType, typename = void>
946 struct is_invocable_impl : std::false_type
947 {
948 };
949 
950 template <typename Result, typename ReturnType>
951 struct is_invocable_impl<Result, ReturnType, void_t<typename Result::type>>
952     : disjunction<std::is_void<ReturnType>,
953                   std::is_convertible<typename Result::type, ReturnType>>::type
954 {
955 };
956 
957 template <typename F, typename... ArgTypes>
958 struct is_invocable
959     : is_invocable_impl<invoke_result<F, ArgTypes...>, void>::type
960 {
961 };
962 
963 template <typename ReturnType, typename F, typename... ArgTypes>
964 struct is_invocable_r
965     : is_invocable_impl<invoke_result<F, ArgTypes...>, ReturnType>::type
966 {
967 };
968 }
969 }
970 
971 #undef FPLUS_INVOKE_RETURN
972 
973 namespace fplus
974 {
975 namespace internal
976 {
977 // C++17 std::apply (http://en.cppreference.com/w/cpp/utility/apply)
978 template <typename F, typename Tuple, std::size_t... I>
apply_impl(F && f,Tuple && t,std::index_sequence<I...>)979 constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>)
980 {
981     return internal::invoke(std::forward<F>(f),
982                           std::get<I>(std::forward<Tuple>(t))...);
983 }
984 
985 template <typename F, typename Tuple>
apply(F && f,Tuple && t)986 constexpr decltype(auto) apply(F&& f, Tuple&& t)
987 {
988     return internal::apply_impl(
989         std::forward<F>(f),
990         std::forward<Tuple>(t),
991         std::make_index_sequence<
992             std::tuple_size<std::decay_t<Tuple>>::value>{});
993 }
994 }
995 }
996 
997 //
998 // internal/asserts/functions.hpp
999 //
1000 
1001 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
1002 // https://github.com/Dobiasd/FunctionalPlus
1003 // Distributed under the Boost Software License, Version 1.0.
1004 // (See accompanying file LICENSE_1_0.txt or copy at
1005 //  http://www.boost.org/LICENSE_1_0.txt)
1006 
1007 
1008 
1009 //
1010 // internal/function_traits_asserts.hpp
1011 //
1012 
1013 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
1014 // https://github.com/Dobiasd/FunctionalPlus
1015 // Distributed under the Boost Software License, Version 1.0.
1016 // (See accompanying file LICENSE_1_0.txt or copy at
1017 //  http://www.boost.org/LICENSE_1_0.txt)
1018 
1019 
1020 
1021 namespace fplus
1022 {
1023 namespace internal
1024 {
1025 template <typename T, typename...>
1026 struct function_traits_asserts;
1027 
1028 template <
1029     typename,
1030     typename F,
1031     typename... Args,
1032     typename std::enable_if<is_invocable<F, Args...>::value, int>::type = 0>
trigger_static_asserts()1033 constexpr void trigger_static_asserts()
1034 {
1035 }
1036 
1037 // Marks a variable as unused. Prevents the compiler warning
1038 // for set but unused variables.
1039 template<class T>
unused(T &&)1040 inline void unused(T&&) { }
1041 
1042 template <typename Tag,
1043           typename F,
1044           typename... Args,
1045           typename std::enable_if<has_function_traits<F>::value &&
1046                                       !is_invocable<F, Args...>::value,
1047                                   int>::type = 0>
trigger_static_asserts()1048 constexpr void trigger_static_asserts()
1049 {
1050     // don't perform checks if function_traits<F> doesn't exist
1051     unused(function_traits_asserts<Tag, F, Args...>{});
1052 }
1053 
1054 template <typename,
1055           typename F,
1056           typename... Args,
1057           typename std::enable_if<!has_function_traits<F>::value &&
1058                                       !is_invocable<F, Args...>::value,
1059                                   int>::type = 0>
trigger_static_asserts()1060 constexpr void trigger_static_asserts()
1061 {
1062   static_assert(sizeof(F) == 0,
1063                 "F is not a Callable, or its definition is ill-formed");
1064 }
1065 }
1066 }
1067 
1068 namespace fplus
1069 {
1070 namespace internal
1071 {
1072 
1073 struct nullary_function_tag
1074 {
1075 };
1076 
1077 struct unary_function_tag
1078 {
1079 };
1080 
1081 struct binary_function_tag
1082 {
1083 };
1084 
1085 struct binary_predicate_tag
1086 {
1087 };
1088 
1089 struct check_arity_tag
1090 {
1091 };
1092 
1093 template <typename F>
1094 struct function_traits_asserts<nullary_function_tag, F>
1095 {
1096     static_assert(utils::function_traits<F>::arity == 0,
1097                   "Function must take no parameters.");
1098 };
1099 
1100 template <typename F, typename X>
1101 struct function_traits_asserts<unary_function_tag, F, X>
1102 {
1103     static_assert(utils::function_traits<F>::arity == 1,
1104                   "Function must take one parameter.");
1105     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
1106     static_assert(std::is_convertible<X, FIn0>::value,
1107                   "Invalid argument type for function");
1108 };
1109 
1110 template <typename F>
1111 struct function_traits_asserts<binary_function_tag, F>
1112 {
1113     static_assert(utils::function_traits<F>::arity == 2,
1114         "Function must take two parameters.");
1115 };
1116 
1117 template <typename F, typename X, typename Y>
1118 struct function_traits_asserts<binary_function_tag, F, X ,Y>
1119 {
1120     static_assert(utils::function_traits<F>::arity == 2,
1121         "Function must take two parameters.");
1122     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
1123     static_assert(std::is_convertible<X, FIn0>::value,
1124                   "Invalid first argument type for function");
1125     typedef typename utils::function_traits<F>::template arg<1>::type FIn1;
1126     static_assert(std::is_convertible<Y, FIn1>::value,
1127                   "Invalid second argument type for function");
1128 };
1129 
1130 template <typename F>
1131 struct function_traits_asserts<binary_predicate_tag, F>
1132 {
1133     static_assert(utils::function_traits<F>::arity == 2,
1134         "Function must take two parameters.");
1135     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
1136     typedef typename utils::function_traits<F>::template arg<1>::type FIn1;
1137     static_assert(std::is_same<FIn0, FIn1>::value,
1138                   "Both parameters must have the same type.");
1139     static_assert(std::is_same<std::decay_t<internal::invoke_result_t<F, FIn0, FIn1>>, bool>::value,
1140                 "Predicate must return bool.");
1141 };
1142 
1143 template <typename F, typename... Args>
1144 struct function_traits_asserts<check_arity_tag, F, Args...>
1145 {
1146     static_assert(utils::function_traits<F>::arity == sizeof...(Args),
1147                   "Wrong arity.");
1148 };
1149 
1150 }
1151 }
1152 
1153 //
1154 // internal/asserts/composition.hpp
1155 //
1156 
1157 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
1158 // https://github.com/Dobiasd/FunctionalPlus
1159 // Distributed under the Boost Software License, Version 1.0.
1160 // (See accompanying file LICENSE_1_0.txt or copy at
1161 //  http://www.boost.org/LICENSE_1_0.txt)
1162 
1163 
1164 
1165 namespace fplus
1166 {
1167 namespace internal
1168 {
1169 
1170 struct bind_1st_of_2_tag
1171 {
1172 };
1173 
1174 struct bind_2nd_of_2_tag
1175 {
1176 };
1177 
1178 struct bind_1st_of_3_tag
1179 {
1180 };
1181 
1182 struct bind_1st_and_2nd_of_3_tag
1183 {
1184 };
1185 
1186 struct bind_2nd_and_3rd_of_3_tag
1187 {
1188 };
1189 
1190 template <typename F, typename X, typename Y>
1191 struct function_traits_asserts<bind_1st_of_2_tag, F, X, Y>
1192 {
1193     static_assert(utils::function_traits<F>::arity == 2,
1194                   "Function must take two parameters.");
1195     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
1196     typedef typename utils::function_traits<F>::template arg<1>::type FIn1;
1197     static_assert(std::is_convertible<X, FIn0>::value,
1198                   "Function can not take bound parameter type");
1199     static_assert(std::is_convertible<Y, FIn1>::value,
1200                   "Function can not take provided parameter type");
1201 };
1202 
1203 template <typename F, typename X, typename Y>
1204 struct function_traits_asserts<bind_2nd_of_2_tag, F, X, Y>
1205 {
1206     static_assert(utils::function_traits<F>::arity == 2,
1207                   "Function must take two parameters.");
1208     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
1209     typedef typename utils::function_traits<F>::template arg<1>::type FIn1;
1210     static_assert(std::is_convertible<X, FIn0>::value,
1211                   "Function can not take provided parameter type");
1212     static_assert(std::is_convertible<Y, FIn1>::value,
1213                   "Function can not take bound parameter type");
1214 };
1215 
1216 template <typename F, typename X, typename Y, typename Z>
1217 struct function_traits_asserts<bind_1st_of_3_tag, F, X, Y, Z>
1218 {
1219     static_assert(utils::function_traits<F>::arity == 3,
1220                   "Function must take three parameters.");
1221     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
1222     typedef typename utils::function_traits<F>::template arg<1>::type FIn1;
1223     typedef typename utils::function_traits<F>::template arg<2>::type FIn2;
1224     static_assert(std::is_convertible<X, FIn0>::value,
1225                   "Function can not take bound parameter type");
1226     static_assert(std::is_convertible<Y, FIn1>::value,
1227                   "Function can not take provided first parameter type");
1228     static_assert(std::is_convertible<Z, FIn2>::value,
1229                   "Function can not take provided second parameter type");
1230 };
1231 
1232 template <typename F, typename X, typename Y, typename Z>
1233 struct function_traits_asserts<bind_1st_and_2nd_of_3_tag, F, X, Y, Z>
1234 {
1235     static_assert(utils::function_traits<F>::arity == 3,
1236                   "Function must take three parameters.");
1237     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
1238     typedef typename utils::function_traits<F>::template arg<1>::type FIn1;
1239     typedef typename utils::function_traits<F>::template arg<2>::type FIn2;
1240     static_assert(std::is_convertible<X, FIn0>::value,
1241                   "Function can not take first bound parameter type");
1242     static_assert(std::is_convertible<Y, FIn1>::value,
1243                   "Function can not take second bound parameter type");
1244     static_assert(std::is_convertible<Z, FIn2>::value,
1245                   "Function can not take provided parameter type");
1246 };
1247 
1248 template <typename F, typename X, typename Y, typename Z>
1249 struct function_traits_asserts<bind_2nd_and_3rd_of_3_tag, F, X, Y, Z>
1250 {
1251     static_assert(utils::function_traits<F>::arity == 3,
1252                   "Function must take three parameters.");
1253     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
1254     typedef typename utils::function_traits<F>::template arg<1>::type FIn1;
1255     typedef typename utils::function_traits<F>::template arg<2>::type FIn2;
1256     static_assert(std::is_convertible<X, FIn0>::value,
1257                   "Function can not take provided parameter type");
1258     static_assert(std::is_convertible<Y, FIn1>::value,
1259                   "Function can not take second bound parameter type");
1260     static_assert(std::is_convertible<Z, FIn2>::value,
1261                   "Function can not take first bound parameter type");
1262 };
1263 
1264 }
1265 }
1266 
1267 //
1268 // internal/composition.hpp
1269 //
1270 
1271 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
1272 // https://github.com/Dobiasd/FunctionalPlus
1273 // Distributed under the Boost Software License, Version 1.0.
1274 // (See accompanying file LICENSE_1_0.txt or copy at
1275 //  http://www.boost.org/LICENSE_1_0.txt)
1276 
1277 
1278 #include <tuple>
1279 #include <utility>
1280 
1281 
1282 namespace fplus
1283 {
1284 namespace internal
1285 {
1286 // source: https://codereview.stackexchange.com/a/63893
1287 // note: the code in the link above is called with the arguments in reverse order
1288 template <typename... Fs>
1289 class compose_impl
1290 {
1291     static constexpr std::size_t size = sizeof...(Fs);
1292     static_assert(size > 1,
1293                   "Invalid number of functions to compose, minimum is two.");
1294 
1295   public:
compose_impl(Fs &&...fs)1296     compose_impl(Fs&&... fs) : _functionTuple(std::forward<Fs>(fs)...)
1297     {
1298     }
1299 
1300     template <typename... Ts>
operator ()(Ts &&...ts) const1301     auto operator()(Ts&&... ts) const
1302     {
1303         return _apply(std::integral_constant<std::size_t, 0>{},
1304                       std::forward<Ts>(ts)...);
1305     }
1306 
1307   private:
1308     template <std::size_t N, typename... Ts>
_apply(std::integral_constant<std::size_t,N>,Ts &&...ts) const1309     auto _apply(std::integral_constant<std::size_t, N>, Ts&&... ts) const
1310     {
1311         return _apply(std::integral_constant<std::size_t, N + 1>{},
1312                       std::get<N>(_functionTuple)(std::forward<Ts>(ts)...));
1313     }
1314 
1315     template <typename... Ts>
_apply(std::integral_constant<std::size_t,size-1>,Ts &&...ts) const1316     auto _apply(std::integral_constant<std::size_t, size - 1>, Ts&&... ts) const
1317     {
1318         return internal::invoke(std::get<size - 1>(_functionTuple),
1319                               std::forward<Ts>(ts)...);
1320     }
1321 
1322     std::tuple<Fs...> _functionTuple;
1323 };
1324 
1325 // Is BinaryLift really correct?
1326 template <typename Tuple, typename BinaryLift>
compose_binary_lift_impl(std::integral_constant<std::size_t,1>,const Tuple & tup,const BinaryLift & lifter)1327 auto compose_binary_lift_impl(std::integral_constant<std::size_t, 1>,
1328                               const Tuple& tup,
1329                               const BinaryLift& lifter)
1330 {
1331     return lifter(std::get<0>(tup), std::get<1>(tup));
1332 }
1333 
1334 template <std::size_t N, typename Tuple, typename BinaryLift>
compose_binary_lift_impl(std::integral_constant<std::size_t,N>,const Tuple & tup,const BinaryLift & lifter)1335 auto compose_binary_lift_impl(std::integral_constant<std::size_t, N>,
1336                               const Tuple& tup,
1337                               const BinaryLift& lifter)
1338 {
1339     return lifter(
1340         compose_binary_lift_impl(
1341             std::integral_constant<std::size_t, N - 1>{}, tup, lifter),
1342         std::get<N>(tup));
1343 }
1344 
1345 template <typename BinaryLift, typename... Callables>
compose_binary_lift(const BinaryLift & lifter,Callables &&...args)1346 auto compose_binary_lift(const BinaryLift& lifter, Callables&&... args)
1347 {
1348     static_assert(sizeof...(Callables) > 1,
1349                   "Invalid number of functions to compose, minimum is two.");
1350     const auto tup = std::forward_as_tuple(std::forward<Callables>(args)...);
1351     return compose_binary_lift_impl(
1352         std::integral_constant<std::size_t, sizeof...(Callables) - 1>{},
1353         tup,
1354         lifter);
1355 }
1356 
1357 // concentrate asserts in this method. Lambda is provided by the library.
1358 template <typename Lambda, typename F, typename G>
logical_binary_op(Lambda op,F f,G g)1359 auto logical_binary_op(Lambda op, F f, G g)
1360 {
1361     // Perfect-forwarding might move twice, if we add a requirement on F and G,
1362     // that might not be an issue.
1363     return [op, f, g](auto x) {
1364         internal::trigger_static_asserts<internal::unary_function_tag,
1365                                              F,
1366                                              decltype(x)>();
1367         internal::trigger_static_asserts<internal::unary_function_tag,
1368                                              G,
1369                                              decltype(x)>();
1370         using FRes = std::decay_t<internal::invoke_result_t<F, decltype(x)>>;
1371         using GRes = std::decay_t<internal::invoke_result_t<G, decltype(x)>>;
1372         static_assert(std::is_same<FRes, bool>::value, "Must return bool.");
1373         static_assert(std::is_same<GRes, bool>::value, "Must return bool.");
1374 
1375         return op(f, g, x);
1376     };
1377 }
1378 }
1379 }
1380 
1381 #include <functional>
1382 #include <map>
1383 #include <memory>
1384 #include <type_traits>
1385 #include <unordered_map>
1386 #include <utility>
1387 
1388 namespace fplus
1389 {
1390 
1391 // API search type: bind_1st_of_2 : (((a, b) -> c), a) -> (b -> c)
1392 // Bind first parameter of binary function.
1393 template <typename F, typename T>
bind_1st_of_2(F f,T x)1394 auto bind_1st_of_2(F f, T x)
1395 {
1396     return [f, x](auto&& y) {
1397         internal::trigger_static_asserts<internal::bind_1st_of_2_tag,
1398                                              F,
1399                                              T,
1400                                              decltype(y)>();
1401         return internal::invoke(f, x, std::forward<decltype(y)>(y));
1402     };
1403 }
1404 
1405 // API search type: bind_2nd_of_2 : (((a, b) -> c), b) -> (a -> c)
1406 // Bind second parameter of binary function.
1407 template <typename F, typename T>
bind_2nd_of_2(F f,T y)1408 auto bind_2nd_of_2(F f, T y)
1409 {
1410     return [f, y](auto&& x) {
1411         internal::trigger_static_asserts<internal::bind_2nd_of_2_tag,
1412                                              F,
1413                                              decltype(x),
1414                                              T>();
1415         return internal::invoke(f, std::forward<decltype(x)>(x), y);
1416     };
1417 }
1418 
1419 // API search type: bind_1st_of_3 : (((a, b, c) -> d), a) -> ((b, c) -> d)
1420 // Bind first parameter of ternary function.
1421 template <typename F, typename X>
bind_1st_of_3(F f,X x)1422 auto bind_1st_of_3(F f, X x)
1423 {
1424     return [f, x](auto&& y, auto&& z) {
1425         internal::trigger_static_asserts<internal::bind_1st_of_3_tag,
1426                                              F,
1427                                              X,
1428                                              decltype(y),
1429                                              decltype(z)>();
1430         return internal::invoke(
1431             f, x, std::forward<decltype(y)>(y), std::forward<decltype(z)>(z));
1432     };
1433 }
1434 
1435 // API search type: bind_1st_and_2nd_of_3 : (((a, b, c) -> d), a, b) -> (c -> d)
1436 // Bind first and second parameter of ternary function.
1437 template <typename F, typename X, typename Y>
bind_1st_and_2nd_of_3(F f,X x,Y y)1438 auto bind_1st_and_2nd_of_3(F f, X x, Y y)
1439 {
1440     return [f, x, y](auto&& z) {
1441         internal::trigger_static_asserts<internal::bind_1st_and_2nd_of_3_tag,
1442                                              F,
1443                                              X,
1444                                              Y,
1445                                              decltype(z)>();
1446         return internal::invoke(f, x, y, std::forward<decltype(z)>(z));
1447     };
1448 }
1449 
1450 // API search type: bind_2nd_and_3rd_of_3 : (((a, b, c) -> d), b, c) -> (a -> d)
1451 // Bind first and second parameter of ternary function.
1452 template <typename F, typename Y, typename Z>
bind_2nd_and_3rd_of_3(F f,Y y,Z z)1453 auto bind_2nd_and_3rd_of_3(F f, Y y, Z z)
1454 {
1455     return [f, y, z](auto&& x) {
1456         internal::trigger_static_asserts<internal::bind_2nd_and_3rd_of_3_tag,
1457                                              F,
1458                                              decltype(x),
1459                                              Y,
1460                                              Z>();
1461         return internal::invoke(f, std::forward<decltype(x)>(x), y, z);
1462     };
1463 }
1464 
1465 // API search type: flip : (a -> b) -> (b -> a)
1466 // Flips the arguments of a binary function
1467 // Note: The callable can take a variadic number of arguments
1468 template <typename F>
flip(F f)1469 auto flip(F f)
1470 {
1471     return [f](auto&&... args) {
1472         return internal::apply_impl(
1473             f,
1474             std::forward_as_tuple(std::forward<decltype(args)>(args)...),
1475             internal::make_reverse_index_sequence<sizeof...(args)>{});
1476     };
1477 }
1478 
1479 // API search type: forward_apply : (a, (a -> b)) -> b
1480 // Forward application.
1481 // Returns the result of applying the function f to the value x.
1482 template <typename X, typename F>
forward_apply(X && x,F f)1483 auto forward_apply(X&& x, F f)
1484 {
1485     internal::trigger_static_asserts<internal::unary_function_tag, F, X>();
1486     return internal::invoke(f, std::forward<X>(x));
1487 }
1488 
1489 // API search type: lazy : ((a -> b), a) -> (() -> b)
1490 // Lazy evaluation.
1491 // Returns a function evaluating f with the given arguments when called.
1492 // Also known as defer.
1493 // Note: f can take a variadic number of parameters
1494 template<typename F, typename... Args>
lazy(F f,Args...args)1495 auto lazy(F f, Args ... args)
1496 {
1497     return [f, args...] {
1498         internal::trigger_static_asserts<internal::check_arity_tag, F, Args...>();
1499         return internal::invoke(f, args...);
1500     };
1501 }
1502 
1503 // API search type: fixed : a -> (() -> a)
1504 // Identity as a nullary function.
1505 // Returns a function returning x when called.
1506 // Like lazy with identity as f.
1507 template<typename T>
fixed(T x)1508 auto fixed(T x)
1509 {
1510     return [x]() -> T
1511     {
1512         return x;
1513     };
1514 }
1515 
1516 // API search type: compose : ((a -> b), (b -> c)) -> (a -> c)
1517 // Forward function composition.
1518 // compose(f, g)(x) = g(f(x))
1519 // It is possible to compose a variadic number of callables.
1520 // The first callable can also take a variadic number of parameters.
1521 // compose(f, g, h)(x, y, z) = h(g(f(x, y, z)))
1522 template <typename... Fs>
compose(Fs &&...fs)1523 auto compose(Fs&&... fs)
1524 {
1525     return internal::compose_impl<Fs...>(std::forward<Fs>(fs)...);
1526 }
1527 
1528 // API search type: logical_not : (a -> Bool) -> (a -> Bool)
1529 // Converts a predicate p into a new one,
1530 // always returning the exact opposite of p.
1531 // logical_not(f) = \x -> !x
1532 // Note: F can take a variadic number of parameters.
1533 // Equivalent to std::not_fn (C++17)
1534 template <typename Predicate>
logical_not(Predicate f)1535 auto logical_not(Predicate f)
1536 {
1537     return [f](auto&&... args) {
1538         internal::trigger_static_asserts<internal::unary_function_tag,
1539                                              Predicate,
1540                                              decltype(args)...>();
1541         using Res =
1542             std::decay_t<internal::invoke_result_t<Predicate, decltype(args)...>>;
1543         static_assert(std::is_same<Res, bool>::value, "Function must return bool.");
1544 
1545         return !internal::invoke(f, std::forward<decltype(args)>(args)...);
1546     };
1547 }
1548 
1549 // API search type: logical_or : ((a -> Bool), (a -> Bool)) -> (a -> Bool)
1550 // logical_or(f, g) = \x -> f(x) or g(x)
1551 // Combines to unary predicates into a single one
1552 // that holds true if at least one of the original predicated is true.
1553 template <typename UnaryPredicateF, typename UnaryPredicateG>
logical_or(UnaryPredicateF f,UnaryPredicateG g)1554 auto logical_or(UnaryPredicateF f, UnaryPredicateG g)
1555 {
1556     auto op = [](auto f1, auto f2, auto x) {
1557         return internal::invoke(f1, x) || internal::invoke(f2, x);
1558     };
1559 
1560     return internal::logical_binary_op(op, f, g);
1561 }
1562 
1563 // API search type: logical_and : ((a -> Bool), (a -> Bool)) -> (a -> Bool)
1564 // logical_and(f, g) = \x -> f(x) and g(x)
1565 // Combines to unary predicates into a single one
1566 // that holds true if both original predicated are true.
1567 template <typename UnaryPredicateF, typename UnaryPredicateG>
logical_and(UnaryPredicateF f,UnaryPredicateG g)1568 auto logical_and(UnaryPredicateF f, UnaryPredicateG g)
1569 {
1570   auto op = [](auto f1, auto f2, auto x) {
1571     return internal::invoke(f1, x) && internal::invoke(f2, x);
1572   };
1573 
1574   return internal::logical_binary_op(op, f, g);
1575 }
1576 
1577 // API search type: logical_xor : ((a -> Bool), (a -> Bool)) -> (a -> Bool)
1578 // logical_xor(f, g) = \x -> f(x) xor g(x)
1579 // Combines to unary predicates into a single one
1580 // that holds true if exactly one of the original predicated is true.
1581 template <typename UnaryPredicateF, typename UnaryPredicateG>
logical_xor(UnaryPredicateF f,UnaryPredicateG g)1582 auto logical_xor(UnaryPredicateF f, UnaryPredicateG g)
1583 {
1584   auto op = [](auto f1, auto f2, auto x) {
1585     return internal::invoke(f1, x) != internal::invoke(f2, x);
1586   };
1587 
1588   return internal::logical_binary_op(op, f, g);
1589 }
1590 
1591 // API search type: memoize : (a -> b) -> (a -> b)
1592 // Provides Memoization for a given (referentially transparent)
1593 // unary function.
1594 // Returns a closure mutating an internally held dictionary
1595 // mapping input values to output values.
1596 template <typename F,
1597     typename FIn = typename utils::function_traits<F>::template arg<0>::type,
1598     typename FOut = typename std::result_of<F(FIn)>::type,
1599     typename MemoMap = std::unordered_map<
1600         typename std::remove_reference<typename std::remove_const<FIn>::type>::type,
1601         FOut>>
memoize(F f)1602 std::function<FOut(FIn)> memoize(F f)
1603 {
1604     static_assert(utils::function_traits<F>::arity == 1, "Wrong arity.");
1605     MemoMap storage;
1606     return [=](FIn x) mutable -> FOut
1607     {
1608         const auto it = storage.find(x);
1609         if (it == storage.end())
1610         {
1611             return storage.emplace(x, internal::invoke(f, x)).first->second;
1612         }
1613         else
1614         {
1615             return it->second;
1616         }
1617     };
1618 }
1619 
1620 namespace internal
1621 {
1622     template <typename F, typename Cache,
1623         typename FIn1 = typename utils::function_traits<F>::template arg<0>::type,
1624         typename FIn2 = typename utils::function_traits<F>::template arg<1>::type,
1625         typename FOut = typename std::result_of<F(FIn1, FIn2)>::type,
1626         typename ResultF = std::function<FOut(FIn2)>>
memoize_recursive_helper(const F f,std::shared_ptr<Cache> storage)1627     ResultF memoize_recursive_helper(const F f, std::shared_ptr<Cache> storage)
1628     {
1629         return [f, storage](FIn2 x)
1630         {
1631             const auto it = storage->find(x);
1632             if (it == storage->end())
1633             {
1634                 const auto g = memoize_recursive_helper(f, storage);
1635                 (*storage)[x] = f(g, x);
1636             }
1637             return (*storage)[x];
1638         };
1639     }
1640 } // namespace internal
1641 
1642 // API search type: memoize_recursive : (a -> b) -> (a -> b)
1643 // Provides Memoization for a given (referentially transparent)
1644 // recursive binary function that takes a continuation as first argument.
1645 // e.g.
1646 // uint64_t fibo_cont(const std::function<uint64_t(uint64_t)>& cont, uint64_t n)
1647 // {
1648 //     if (n < 2) return n;
1649 //     else return cont(n-1) + cont(n-2);
1650 // }
1651 // Returns a closure mutating an internally held dictionary
1652 // mapping input values to output values.
1653 template <typename F,
1654     typename FIn1 = typename utils::function_traits<F>::template arg<0>::type,
1655     typename FIn2 = typename utils::function_traits<F>::template arg<1>::type,
1656     typename FOut = typename std::result_of<F(FIn1, FIn2)>::type,
1657     typename MemoMap = std::unordered_map<
1658         typename std::remove_reference<typename std::remove_const<FIn2>::type>::type,
1659         FOut>>
memoize_recursive(F f)1660 std::function<FOut(FIn2)> memoize_recursive(F f)
1661 {
1662     std::shared_ptr<MemoMap> storage = std::make_shared<MemoMap>();
1663     return internal::memoize_recursive_helper(f, storage);
1664 }
1665 
1666 // API search type: memoize_binary : ((a, b) -> c) -> ((a, b) -> c)
1667 // Provides Memoization for a given (referentially transparent)
1668 // binary function.
1669 // Returns a closure mutating an internally held dictionary
1670 // mapping input values to output values.
1671 template <typename F,
1672     typename FIn1 = typename utils::function_traits<F>::template arg<0>::type,
1673     typename FIn2 = typename utils::function_traits<F>::template arg<1>::type,
1674     typename FOut = typename std::result_of<F(FIn1, FIn2)>::type,
1675     typename ParamPair = std::pair<
1676         typename std::remove_reference<typename std::remove_const<FIn1>::type>::type,
1677         typename std::remove_reference<typename std::remove_const<FIn2>::type>::type>,
1678     typename MemoMap = std::unordered_map<ParamPair, FOut>>
memoize_binary(F f)1679 std::function<FOut(FIn1, FIn2)> memoize_binary(F f)
1680 {
1681     const auto unary_f = [f](const ParamPair& params) -> FOut
1682     {
1683         return internal::invoke(f, params.first, params.second);
1684     };
1685     auto unary_f_memoized = memoize<decltype(unary_f),
1686         ParamPair, FOut, std::map<ParamPair, FOut>>(unary_f);
1687     return [unary_f_memoized](FIn1 a, FIn2 b) mutable -> FOut
1688     {
1689         return unary_f_memoized(std::make_pair(a, b));
1690     };
1691 }
1692 
1693 // API search type: constructor_as_function : a -> b
1694 // struct foo
1695 // {
1696 //     foo(int a, int b) : a_(a), b_(2*b) {}
1697 //     int a_;
1698 //     int b_;
1699 // };
1700 // const auto create_foo = constructor_as_function<foo, int, int>;
1701 // create_foo(1,2) == foo(1, 2);
1702 template <typename T, class ... Types>
1703 T constructor_as_function(Types ... args)
1704 {
1705     return T(args...);
1706 }
1707 
1708 } // namespace fplus
1709 
1710 #define fplus_get_mem(fplus_get_mem_name) \
1711 [](const auto& fplus_get_mem_x) \
1712 { \
1713     return fplus_get_mem_x.fplus_get_mem_name; \
1714 }
1715 
1716 #define fplus_get_ptr_mem(fplus_get_ptr_mem_name) \
1717 [](const auto& fplus_get_ptr_mem_x) \
1718 { \
1719     return fplus_get_ptr_mem_x->fplus_get_ptr_mem_name; \
1720 }
1721 
1722 #define fplus_get_c_mem_t(fplus_get_c_mem_t_c, fplus_get_c_mem_t_name, fplus_get_c_mem_t_t) \
1723 [](const fplus_get_c_mem_t_c& fplus_get_c_mem_t_x) -> fplus_get_c_mem_t_t \
1724 { \
1725     return fplus_get_c_mem_t_x.fplus_get_c_mem_t_name; \
1726 }
1727 
1728 #define fplus_get_c_ptr_mem_t(fplus_get_c_ptr_mem_t_c, fplus_get_c_ptr_mem_t_name, fplus_get_c_ptr_mem_t_t) \
1729 [](const fplus_get_c_ptr_mem_t_c& fplus_get_c_ptr_mem_t_x) -> fplus_get_c_ptr_mem_t_t \
1730 { \
1731     return fplus_get_c_ptr_mem_t_x->fplus_get_c_ptr_mem_t_name; \
1732 }
1733 
1734 #define fplus_mem_fn(fplus_mem_fn_name) \
1735 [](const auto& fplus_mem_fn_x) \
1736 { \
1737     return fplus_mem_fn_x.fplus_mem_fn_name(); \
1738 }
1739 
1740 #define fplus_ptr_mem_fn(fplus_ptr_mem_fn_name) \
1741 [](const auto& fplus_ptr_mem_fn_x) \
1742 { \
1743     return fplus_ptr_mem_fn_x->fplus_ptr_mem_fn_name(); \
1744 }
1745 
1746 #define fplus_c_mem_fn_t(fplus_c_mem_fn_t_c, fplus_c_mem_fn_t_name, fplus_c_mem_fn_t_t) \
1747 [](const fplus_c_mem_fn_t_c& fplus_c_mem_fn_t_x) -> fplus_c_mem_fn_t_t \
1748 { \
1749     return fplus_c_mem_fn_t_x.fplus_c_mem_fn_t_name(); \
1750 }
1751 
1752 #define fplus_c_ptr_mem_fn_t(fplus_c_ptr_mem_fn_t_c, fplus_c_ptr_mem_fn_t_name, fplus_c_ptr_mem_fn_t_t) \
1753 [](const fplus_c_ptr_mem_fn_t_c& fplus_c_ptr_mem_fn_t_x) -> fplus_c_ptr_mem_fn_t_t \
1754 { \
1755     return fplus_c_ptr_mem_fn_t_x->fplus_c_ptr_mem_fn_t_name(); \
1756 }
1757 
1758 
1759 //
1760 // internal/compare.hpp
1761 //
1762 
1763 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
1764 // https://github.com/Dobiasd/FunctionalPlus
1765 // Distributed under the Boost Software License, Version 1.0.
1766 // (See accompanying file LICENSE_1_0.txt or copy at
1767 //  http://www.boost.org/LICENSE_1_0.txt)
1768 
1769 
1770 #include <type_traits>
1771 
1772 
1773 namespace fplus
1774 {
1775 namespace internal
1776 {
1777 template <typename Compare>
ord_to_impl(Compare comp)1778 auto ord_to_impl(Compare comp)
1779 {
1780     return [comp](auto x, auto y)
1781     {
1782         static_assert(std::is_same<decltype(x), decltype(y)>::value,
1783             "Argument types must be the same");
1784         using In = decltype(x);
1785         internal::trigger_static_asserts<internal::binary_predicate_tag, Compare, In, In>();
1786 
1787         using CompareOut = std::decay_t<internal::invoke_result_t<Compare, In, In>>;
1788         static_assert(std::is_same<CompareOut, bool>::value,
1789                       "Function must return bool.");
1790         return std::make_pair(internal::invoke(comp, x, y),
1791                               internal::invoke(comp, y, x));
1792     };
1793 }
1794 }
1795 }
1796 
1797 namespace fplus
1798 {
1799 
1800 namespace internal
1801 {
1802     template <typename UnaryPredicate, typename T>
check_unary_predicate_for_type()1803     void check_unary_predicate_for_type()
1804     {
1805         internal::trigger_static_asserts<internal::unary_function_tag, UnaryPredicate, T>();
1806         static_assert(std::is_convertible<
1807             internal::invoke_result_t<UnaryPredicate, T>, bool>::value,
1808             "Predicate must return bool.");
1809     }
1810     template <typename F, typename G, typename X, typename Y>
check_compare_preprocessors_for_types()1811     void check_compare_preprocessors_for_types()
1812     {
1813         internal::trigger_static_asserts<internal::unary_function_tag, F, X>();
1814         internal::trigger_static_asserts<internal::unary_function_tag, G, Y>();
1815         static_assert(std::is_same<
1816             std::decay_t<internal::invoke_result_t<F, X>>,
1817             std::decay_t<internal::invoke_result_t<G, Y>>>::value,
1818             "Both functions must return the same type.");
1819     }
1820 } // namespace internal
1821 
1822 // API search type: identity : a -> a
1823 // fwd bind count: 0
1824 // identity(x) == x
1825 template <typename T>
identity(const T & x)1826 T identity(const T& x)
1827 {
1828     return x;
1829 }
1830 
1831 // API search type: is_equal : (a, a) -> Bool
1832 // fwd bind count: 1
1833 // x == y
1834 // Equality check.
1835 template <typename T>
is_equal(const T & x,const T & y)1836 bool is_equal(const T& x, const T& y)
1837 {
1838     return x == y;
1839 }
1840 
1841 // API search type: always : a -> (b -> a)
1842 // always(x)(y) == x
1843 template <typename X>
always(const X & x)1844 auto always(const X& x)
1845 {
1846     return [x](const auto&) { return x; };
1847 }
1848 
1849 // API search type: always_arg_1_of_2 : (a, b) -> a
1850 // always_arg_1_of_2(x, y) == x
1851 template <typename X, typename Y>
1852 X always_arg_1_of_2(const X& x, const Y&)
1853 {
1854     return x;
1855 }
1856 
1857 // API search type: always_arg_2_of_2 : (a, b) -> a
1858 // always_arg_2_of_2(x, y) == x
1859 template <typename X, typename Y>
always_arg_2_of_2(const X &,const Y & y)1860 Y always_arg_2_of_2(const X&, const Y& y)
1861 {
1862     return y;
1863 }
1864 
1865 // API search type: is_equal_by_and_by : ((a -> b), (c -> b)) -> ((a, c) -> Bool)
1866 // f(x) == g(y)
1867 // Provides an equality check of two values
1868 // after applying a transformation function each.
1869 template <typename F, typename G>
is_equal_by_and_by(F f,G g)1870 auto is_equal_by_and_by(F f, G g)
1871 {
1872     return [f, g](const auto& x, const auto& y) {
1873         internal::trigger_static_asserts<internal::unary_function_tag,
1874                                              F,
1875                                              decltype(x)>();
1876         internal::trigger_static_asserts<internal::unary_function_tag,
1877                                              G,
1878                                              decltype(y)>();
1879         return is_equal(internal::invoke(f, x), internal::invoke(g, y));
1880     };
1881 }
1882 
1883 // API search type: is_equal_by : (a -> b) -> (a -> Bool)
1884 // f(x) == f(y)
1885 // Provides an equality check of two values
1886 // after applying the same transformation function to both.
1887 template <typename F>
is_equal_by(F f)1888 auto is_equal_by(F f)
1889 {
1890     return is_equal_by_and_by(f, f);
1891 }
1892 
1893 // API search type: is_equal_by_to : ((b -> a), a) -> (b -> Bool)
1894 // f(y) == x
1895 // Provides an equality check to a fixed value
1896 // after applying a transformation function.
1897 template <typename F, typename X>
is_equal_by_to(F f,const X & x)1898 auto is_equal_by_to(F f, const X& x)
1899 {
1900     return [f, x](const auto& y)
1901     {
1902         internal::trigger_static_asserts<internal::unary_function_tag,
1903                                              F,
1904                                              decltype(y)>();
1905         return is_equal(internal::invoke(f, y), x);
1906     };
1907 }
1908 
1909 // API search type: is_equal_to : a -> (a -> Bool)
1910 // x == y
1911 // curried version of is_equal
1912 // Provides an equality check with a fixed value.
1913 template <typename X>
is_equal_to(const X & x)1914 auto is_equal_to(const X& x)
1915 {
1916     return is_equal_by_to(identity<X>, x);
1917 }
1918 
1919 // API search type: is_not_equal : (a, a) -> Bool
1920 // fwd bind count: 1
1921 // x != y
1922 // Unequally check.
1923 template <typename T>
is_not_equal(const T & x,const T & y)1924 bool is_not_equal(const T& x, const T& y)
1925 {
1926     return x != y;
1927 }
1928 
1929 // API search type: is_not_equal_by_and_by : ((a -> c), (b -> c)) -> ((a, b) -> Bool)
1930 // f(x) != g(y)
1931 // Provides an unequality check of two values
1932 // after applying a transformation function eac
1933 template <typename F, typename G>
is_not_equal_by_and_by(F f,G g)1934 auto is_not_equal_by_and_by(F f, G g)
1935 {
1936     return [f, g](const auto& x, const auto& y) {
1937         internal::trigger_static_asserts<internal::unary_function_tag,
1938                                              F,
1939                                              decltype(x)>();
1940         internal::trigger_static_asserts<internal::unary_function_tag,
1941                                              G,
1942                                              decltype(y)>();
1943         using FOut = std::decay_t<internal::invoke_result_t<F, decltype(x)>>;
1944         using GOut = std::decay_t<internal::invoke_result_t<G, decltype(y)>>;
1945         static_assert(std::is_same<FOut, GOut>::value,
1946                       "Functions must return the same type.");
1947         return is_not_equal(internal::invoke(f, x), internal::invoke(g, y));
1948     };
1949 }
1950 
1951 // API search type: is_not_equal_by : (a -> b) -> ((a, a) -> Bool)
1952 // f(x) != f(y)
1953 // Provides an unequality check of two values
1954 // after applying the same transformation function to both.
1955 template <typename F>
is_not_equal_by(F f)1956 auto is_not_equal_by(F f)
1957 {
1958     return is_not_equal_by_and_by(f, f);
1959 }
1960 
1961 // API search type: is_not_equal_by_to : ((a -> b), b) -> (a -> Bool)
1962 // f(y) != x
1963 // Provides an unequality check to a fixed value
1964 // after applying a transformation function.
1965 template <typename F, typename X>
is_not_equal_by_to(F f,const X & x)1966 auto is_not_equal_by_to(F f, const X& x)
1967 {
1968     return [f, x](const auto& y) {
1969         internal::trigger_static_asserts<internal::unary_function_tag,
1970                                              F,
1971                                              decltype(y)>();
1972         return is_not_equal(internal::invoke(f, y), x);
1973     };
1974 }
1975 
1976 // API search type: is_not_equal_to : a -> (a -> Bool)
1977 // y != x
1978 // curried version of is_not_equal
1979 // Provides an unequality check with a fixed value.
1980 template <typename X>
is_not_equal_to(const X & x)1981 auto is_not_equal_to(const X& x)
1982 {
1983     return is_not_equal_by_to(identity<X>, x);
1984 }
1985 
1986 // API search type: is_less : (a, a) -> Bool
1987 // fwd bind count: 1
1988 // x < y
1989 // Less check.
1990 template <typename T>
is_less(const T & x,const T & y)1991 bool is_less(const T& x, const T& y)
1992 {
1993     return x < y;
1994 }
1995 
1996 // API search type: is_less_by_and_by : ((a -> c), (b -> c)) -> ((a, b) -> Bool)
1997 // f(x) < g(y)
1998 // Provides a less check of two values
1999 // after applying a transformation function each.
2000 template <typename F, typename G>
is_less_by_and_by(F f,G g)2001 auto is_less_by_and_by(F f, G g)
2002 {
2003     return [f, g](const auto& x, const auto& y)
2004     {
2005         internal::trigger_static_asserts<internal::unary_function_tag,
2006                                              F,
2007                                              decltype(x)>();
2008         internal::trigger_static_asserts<internal::unary_function_tag,
2009                                              G,
2010                                              decltype(y)>();
2011         using FOut = std::decay_t<internal::invoke_result_t<F, decltype(x)>>;
2012         using GOut = std::decay_t<internal::invoke_result_t<G, decltype(y)>>;
2013         static_assert(std::is_same<FOut, GOut>::value,
2014                       "Functions must return the same type.");
2015         return is_less(internal::invoke(f, x), internal::invoke(g, y));
2016     };
2017 }
2018 
2019 // API search type: is_less_by : (a -> b) -> ((a, a) -> Bool)
2020 // f(x) < f(y)
2021 // Provides a less check of two values
2022 // after applying the same transformation function to both.
2023 template <typename F>
is_less_by(F f)2024 auto is_less_by(F f)
2025 {
2026     return is_less_by_and_by(f, f);
2027 }
2028 
2029 // API search type: is_less_by_than : ((a -> b), b) -> (a -> Bool)
2030 // f(y) < x
2031 // Provides a less check to a fixed value
2032 // after applying a transformation function.
2033 template <typename F, typename X>
is_less_by_than(F f,const X & x)2034 auto is_less_by_than(F f, const X& x)
2035 {
2036     return [f, x](const auto& y)
2037     {
2038         internal::trigger_static_asserts<internal::unary_function_tag,
2039                                              F,
2040                                              decltype(y)>();
2041         return is_less(internal::invoke(f, y), x);
2042     };
2043 }
2044 
2045 // API search type: is_less_than : a -> (a -> Bool)
2046 // y < x
2047 // curried version of is_less
2048 // Provides a less check with a fixed value.
2049 template <typename X>
is_less_than(const X & x)2050 auto is_less_than(const X& x)
2051 {
2052     return is_less_by_than(identity<X>, x);
2053 }
2054 
2055 // API search type: is_less_or_equal : (a, a) -> Bool
2056 // fwd bind count: 1
2057 // x <= y
2058 // Less-or-equal check.
2059 template <typename T>
is_less_or_equal(const T & x,const T & y)2060 bool is_less_or_equal(const T& x, const T& y)
2061 {
2062     return x <= y;
2063 }
2064 
2065 // API search type: is_less_or_equal_by_and_by : ((a -> c), (b -> c)) -> ((a, b) -> Bool)
2066 // f(x) <= g(y)
2067 // Provides a less-or-equal check of two values
2068 // after applying a transformation function each.
2069 template <typename F, typename G>
is_less_or_equal_by_and_by(F f,G g)2070 auto is_less_or_equal_by_and_by(F f, G g)
2071 {
2072     return [f, g](const auto& x, const auto& y)
2073     {
2074         using FIn = decltype(x);
2075         using GIn = decltype(y);
2076         internal::check_compare_preprocessors_for_types<F, G, FIn, GIn>();
2077         return is_less_or_equal(internal::invoke(f, x), internal::invoke(g, y));
2078     };
2079 }
2080 
2081 // API search type: is_less_or_equal_by : (a -> b) -> ((a, a) -> Bool)
2082 // f(x) <= f(y)
2083 // Provides a less-or-equal check of two values
2084 // after applying the same transformation function to both.
2085 template <typename F>
is_less_or_equal_by(F f)2086 auto is_less_or_equal_by(F f)
2087 {
2088     return is_less_or_equal_by_and_by(f, f);
2089 }
2090 
2091 // API search type: is_less_or_equal_by_than : ((a -> b), b) -> (a -> Bool)
2092 // f(y) <= x
2093 // Provides a less-or-equal check to a fixed value
2094 // after applying a transformation function.
2095 template <typename F, typename X>
is_less_or_equal_by_than(F f,const X & x)2096 auto is_less_or_equal_by_than(F f, const X& x)
2097 {
2098     return [f, x](const auto& y)
2099     {
2100         internal::
2101             trigger_static_asserts<internal::unary_function_tag, F, decltype(y)>();
2102         return is_less_or_equal(internal::invoke(f, y), x);
2103     };
2104 }
2105 
2106 // API search type: is_less_or_equal_than : a -> (a -> Bool)
2107 // y <= x
2108 // curried version of is_less_or_equal
2109 // Provides a less-or-equal check with a fixed value
2110 template <typename X>
is_less_or_equal_than(const X & x)2111 auto is_less_or_equal_than(const X& x)
2112 {
2113     return is_less_or_equal_by_than(identity<X>, x);
2114 }
2115 
2116 // API search type: is_greater : a -> a -> Bool
2117 // fwd bind count: 1
2118 // x > y
2119 // Greater check.
2120 template <typename T>
is_greater(const T & x,const T & y)2121 bool is_greater(const T& x, const T& y)
2122 {
2123     return x > y;
2124 }
2125 
2126 // API search type: is_greater_by_and_by : ((a -> c), (b -> c)) -> ((a, b) -> Bool)
2127 // f(x) > g(y)
2128 // Provides a greater check of two values
2129 // after applying a transformation function each.
2130 template <typename F, typename G>
is_greater_by_and_by(F f,G g)2131 auto is_greater_by_and_by(F f, G g)
2132 {
2133     return [f, g](const auto& x, const auto& y)
2134     {
2135         using FIn = decltype(x);
2136         using GIn = decltype(y);
2137 
2138         internal::check_compare_preprocessors_for_types<F, G, FIn, GIn>();
2139         return is_greater(internal::invoke(f, x), internal::invoke(g, y));
2140     };
2141 }
2142 
2143 // API search type: is_greater_by : (a -> b) -> ((a, a) -> Bool)
2144 // f(x) > f(y)
2145 // Provides a greater check of two values
2146 // after applying the same transformation function to both.
2147 template <typename F>
is_greater_by(F f)2148 auto is_greater_by(F f)
2149 {
2150     return is_greater_by_and_by(f, f);
2151 }
2152 
2153 // API search type: is_greater_by_than : ((a -> b), b) -> (a -> Bool)
2154 // f(y) > x
2155 // Provides a greater check to a fixed value
2156 // after applying a transformation function.
2157 template <typename F, typename X>
is_greater_by_than(F f,const X & x)2158 auto is_greater_by_than(F f, const X& x)
2159 {
2160     return [f, x](const auto& y)
2161     {
2162         return is_greater(internal::invoke(f, y), x);
2163     };
2164 }
2165 
2166 // API search type: is_greater_than : a -> (a -> Bool)
2167 // y > x
2168 // curried version of is_greater
2169 // Provides a greater check with a fixed value.
2170 template <typename X>
is_greater_than(const X & x)2171 auto is_greater_than(const X& x)
2172 {
2173     return is_greater_by_than(identity<X>, x);
2174 }
2175 
2176 // API search type: is_greater_or_equal : (a, a) -> Bool
2177 // fwd bind count: 1
2178 // x >= y
2179 // Greater-or-equal check.
2180 template <typename T>
is_greater_or_equal(const T & x,const T & y)2181 bool is_greater_or_equal(const T& x, const T& y)
2182 {
2183     return x >= y;
2184 }
2185 
2186 // API search type: is_greater_or_equal_by_and_by : ((a -> c), (b -> c)) -> ((a, b) -> Bool)
2187 // f(x) >= g(y)
2188 // Provides a greater-or-equal check of two values
2189 // after applying a transformation function each.
2190 template <typename F, typename G>
is_greater_or_equal_by_and_by(F f,G g)2191 auto is_greater_or_equal_by_and_by(F f, G g)
2192 {
2193     return [f, g](const auto& x, const auto& y)
2194     {
2195         using FIn = decltype(x);
2196         using GIn = decltype(y);
2197         internal::check_compare_preprocessors_for_types<F, G, FIn, GIn>();
2198         return is_greater_or_equal(internal::invoke(f, x), internal::invoke(g, y));
2199     };
2200 }
2201 
2202 // API search type: is_greater_or_equal_by : (a -> b) -> ((a, a) -> Bool)
2203 // f(x) >= f(y)
2204 // Provides a greater-or-equal check of two values
2205 // after applying the same transformation function to both.
2206 template <typename F>
is_greater_or_equal_by(F f)2207 auto is_greater_or_equal_by(F f)
2208 {
2209     return is_greater_or_equal_by_and_by(f, f);
2210 }
2211 
2212 // API search type: is_greater_or_equal_by_than : ((a -> b), b) -> (a -> Bool)
2213 // f(y) >= x
2214 // Provides a greater-or-equal check to a fixed value
2215 // after applying a transformation function.
2216 template <typename F, typename X>
is_greater_or_equal_by_than(F f,const X & x)2217 auto is_greater_or_equal_by_than(F f, const X& x)
2218 {
2219     return [f, x](const auto& y)
2220     {
2221         internal::trigger_static_asserts<internal::unary_function_tag, F, decltype(y)>();
2222         return is_greater_or_equal(internal::invoke(f, y), x);
2223     };
2224 }
2225 
2226 // API search type: is_greater_or_equal_than : a -> (a -> Bool)
2227 // y >= x
2228 // curried version of is_less_or_equal
2229 // Provides a greater-or-equal check with a fixed valu
2230 template <typename X>
is_greater_or_equal_than(const X & x)2231 auto is_greater_or_equal_than(const X& x)
2232 {
2233     return is_greater_or_equal_by_than(identity<X>, x);
2234 }
2235 
2236 // API search type: xor_bools : (Bool, Bool) -> Bool
2237 // fwd bind count: 1
2238 // Exclusive or.
2239 template <typename T>
xor_bools(const T & x,const T & y)2240 bool xor_bools(const T& x, const T& y)
2241 {
2242     static_assert(std::is_convertible<T, bool>::value,
2243         "Type must be convertible to bool.");
2244     return (x && !y) || (!x && y);
2245 }
2246 
2247 // API search type: ord_to_eq : ((a, a) -> Bool) -> ((a, a) -> Bool)
2248 // ord_to_eq((<)) == (==)
2249 // Takes a less-than function and converts it
2250 // into an equality check function
2251 // which considers two values as equal if none are lesser than the other one.
2252 template <typename Compare>
ord_to_eq(Compare comp)2253 auto ord_to_eq(Compare comp)
2254 {
2255     return [comp](auto x, auto y)
2256     {
2257         static_assert(std::is_same<decltype(x), decltype(y)>::value,
2258             "Argument types must be the same");
2259         auto p = internal::ord_to_impl(comp)(x, y);
2260         return !p.first && !p.second;
2261     };
2262 }
2263 
2264 // API search type: ord_to_not_eq : ((a, a) -> Bool) -> ((a, a) -> Bool)
2265 // ord_to_not_eq((<)) == (!=)
2266 // Takes a less-than function and converts it
2267 // into an inequality check function
2268 // which considers to values as unequal if one is less than the other one.
2269 template <typename Compare>
ord_to_not_eq(Compare comp)2270 auto ord_to_not_eq(Compare comp)
2271 {
2272     return logical_not(ord_to_eq(comp));
2273 }
2274 
2275 // API search type: ord_eq_to_eq : ((a, a) -> Bool) -> ((a, a) -> Bool)
2276 // ord_eq_to_eq((<=)) == (==)
2277 // ord_to_eq((<)) == (==)
2278 // Takes a less-or-equal-than function and converts it
2279 // into an equality check function
2280 // which considers to values as equal if a <= b and b <= a.
2281 template <typename Compare>
ord_eq_to_eq(Compare comp)2282 auto ord_eq_to_eq(Compare comp)
2283 {
2284     return [comp](auto x, auto y)
2285     {
2286         static_assert(std::is_same<decltype(x), decltype(y)>::value,
2287             "Argument types must be the same");
2288         auto p = internal::ord_to_impl(comp)(x, y);
2289         return p.first && p.second;
2290     };
2291 }
2292 
2293 // API search type: ord_eq_to_not_eq : ((a, a) -> Bool) -> ((a, a) -> Bool)
2294 // ord_eq_to_not_eq((<=)) == (!=)
2295 // Takes a less-or-equal-than function and converts it
2296 // into an inequality check function
2297 // which considers to values as equal if not a <= b and not b <= a.
2298 template <typename Compare>
ord_eq_to_not_eq(Compare comp)2299 auto ord_eq_to_not_eq(Compare comp)
2300 {
2301   return logical_not(ord_eq_to_eq(comp));
2302 }
2303 
2304 } // namespace fplus
2305 
2306 //
2307 // container_common.hpp
2308 //
2309 
2310 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
2311 // https://github.com/Dobiasd/FunctionalPlus
2312 // Distributed under the Boost Software License, Version 1.0.
2313 // (See accompanying file LICENSE_1_0.txt or copy at
2314 //  http://www.boost.org/LICENSE_1_0.txt)
2315 
2316 
2317 
2318 //
2319 // container_traits.hpp
2320 //
2321 
2322 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
2323 // https://github.com/Dobiasd/FunctionalPlus
2324 // Distributed under the Boost Software License, Version 1.0.
2325 // (See accompanying file LICENSE_1_0.txt or copy at
2326 //  http://www.boost.org/LICENSE_1_0.txt)
2327 
2328 
2329 #include <array>
2330 #include <deque>
2331 #include <forward_list>
2332 #include <list>
2333 #include <map>
2334 #include <limits>
2335 #include <unordered_map>
2336 #include <unordered_set>
2337 #include <queue>
2338 #include <set>
2339 #include <stack>
2340 #include <string>
2341 #include <vector>
2342 
2343 
2344 namespace fplus
2345 {
2346 
2347 namespace internal
2348 {
2349 
2350 #ifdef __GNUC__
2351 #pragma GCC diagnostic push
2352 #pragma GCC diagnostic ignored "-Weffc++"
2353 #endif
2354 
2355 template<class T> struct has_order : public std::false_type {};
2356 template<class T, std::size_t N> struct has_order<std::array<T, N>> : public std::true_type {};
2357 template<class T, class Alloc> struct has_order<std::vector<T, Alloc>> : public std::true_type {};
2358 template<class T, class Alloc> struct has_order<std::deque<T, Alloc>> : public std::true_type {};
2359 template<class T, class Alloc> struct has_order<std::forward_list<T, Alloc>> : public std::true_type {};
2360 template<class T, class Alloc> struct has_order<std::list<T, Alloc>> : public std::true_type {};
2361 template<class T, class Alloc> struct has_order<std::set<T, Alloc>> : public std::false_type {};
2362 template<class T, class Container> struct has_order<std::stack<T, Container>> : public std::true_type {};
2363 template<class T, class Container> struct has_order<std::queue<T, Container>> : public std::true_type {};
2364 template<class T, class Container, class Compare> struct has_order<std::priority_queue<T, Container, Compare>> : public std::false_type {};
2365 template<class CharT, class Traits, class Alloc> struct has_order<std::basic_string<CharT, Traits, Alloc>> : public std::true_type {};
2366 
2367 // http://stackoverflow.com/a/33828321/1866775
2368 template<class Cont, class NewT, int SizeOffset = std::numeric_limits<int>::lowest()> struct same_cont_new_t : public std::false_type{};
2369 template<class T, std::size_t N, class NewT, int SizeOffset> struct same_cont_new_t<std::array<T, N>, NewT, SizeOffset>
2370 {
2371     static_assert(SizeOffset != std::numeric_limits<int>::lowest(), "Size of std::array must be known at compile-time.");
2372     typedef typename std::array<NewT, static_cast<std::size_t>(static_cast<int>(N) + SizeOffset)> type;
2373 };
2374 template<class T, template<class> class Alloc, class NewT, int SizeOffset> struct same_cont_new_t<std::vector<T, Alloc<T>>, NewT, SizeOffset> { typedef typename std::vector<NewT, Alloc<NewT>> type; };
2375 template<class T, template<class> class Alloc, class NewT, int SizeOffset> struct same_cont_new_t<std::deque<T, Alloc<T>>, NewT, SizeOffset> { typedef typename std::deque<NewT, Alloc<NewT>> type; };
2376 template<class T, template<class> class Alloc, class NewT, int SizeOffset> struct same_cont_new_t<std::forward_list<T, Alloc<T>>, NewT, SizeOffset> { typedef typename std::forward_list<NewT, Alloc<NewT>> type; };
2377 template<class T, template<class> class Alloc, class NewT, int SizeOffset> struct same_cont_new_t<std::list<T, Alloc<T>>, NewT, SizeOffset> { typedef typename std::list<NewT, Alloc<NewT>> type; };
2378 template<class T, template<class> class Alloc, class NewT, int SizeOffset> struct same_cont_new_t<std::set<T, Alloc<T>>, NewT, SizeOffset> { typedef typename std::set<NewT, Alloc<NewT>> type; };
2379 template<class T, class Container, class NewT, int SizeOffset> struct same_cont_new_t<std::stack<T, Container>, NewT, SizeOffset> { typedef typename std::stack<NewT, Container> type; };
2380 template<class T, class Container, class NewT, int SizeOffset> struct same_cont_new_t<std::queue<T, Container>, NewT, SizeOffset> { typedef typename std::queue<NewT, Container> type; };
2381 template<class T, class Container, class Compare, class NewT, int SizeOffset> struct same_cont_new_t<std::priority_queue<T, Container, Compare>, NewT, SizeOffset> { typedef typename std::priority_queue<NewT, Container, Compare> type; };
2382 template<class CharT, class Traits, class Alloc, class NewT, int SizeOffset> struct same_cont_new_t<std::basic_string<CharT, Traits, Alloc>, NewT, SizeOffset> { typedef typename std::basic_string<NewT, Traits, Alloc> type; };
2383 
2384 // For aligned allocators.
2385 template<class T, template<class, std::size_t> class Alloc, class NewT, int SizeOffset, std::size_t N> struct same_cont_new_t<std::vector<T, Alloc<T, N>>, NewT, SizeOffset> { typedef typename std::vector<NewT, Alloc<NewT, N>> type; };
2386 template<class T, template<class, std::size_t> class Alloc, class NewT, int SizeOffset, std::size_t N> struct same_cont_new_t<std::deque<T, Alloc<T, N>>, NewT, SizeOffset> { typedef typename std::deque<NewT, Alloc<NewT, N>> type; };
2387 
2388 template<class Cont, class NewKey, class NewVal> struct SameMapTypeNewTypes : public std::false_type {};
2389 template<class Key, class T, class Compare, class Alloc, class NewKey, class NewVal> struct SameMapTypeNewTypes<std::map<Key, T, Compare, Alloc>, NewKey, NewVal> { typedef typename std::map<NewKey, NewVal> type; };
2390 template<class Key, class T, class Compare, class Alloc, class NewKey, class NewVal> struct SameMapTypeNewTypes<std::unordered_map<Key, T, Compare, Alloc>, NewKey, NewVal> { typedef typename std::unordered_map<NewKey, NewVal> type; };
2391 
2392 #ifdef __GNUC__
2393 #pragma GCC diagnostic pop
2394 #endif
2395 
2396 template<
2397     typename ContIn,
2398     typename F,
2399     int SizeOffset = std::numeric_limits<int>::lowest(),
2400     typename T = typename ContIn::value_type,
2401     typename ContOut = typename same_cont_new_t<ContIn, std::decay_t<internal::invoke_result_t<F, T>>, SizeOffset>::type>
2402 struct same_cont_new_t_from_unary_f
2403 {
2404     typedef ContOut type;
2405 };
2406 
2407 template<
2408     typename ContIn,
2409     typename F,
2410     typename T1,
2411     typename T2,
2412     int SizeOffset = std::numeric_limits<int>::lowest(),
2413     typename ContOut = typename same_cont_new_t<ContIn, std::decay_t<internal::invoke_result_t<F, T1, T2>>, SizeOffset>::type>
2414 struct same_cont_new_t_from_binary_f
2415 {
2416     typedef ContOut type;
2417 };
2418 
2419 
2420 
2421 // https://stackoverflow.com/a/44549820/1866775
2422 
2423 template<class T>
2424 struct can_self_assign {
2425     using type = std::is_assignable<T&, T>;
2426 };
2427 
2428 template<typename T>
2429 using can_self_assign_t = typename can_self_assign<T>::type;
2430 
2431 template<typename T0, typename T1>
2432 struct can_self_assign<std::pair<T0, T1>>
2433 {
2434     enum { t0 = can_self_assign_t<T0>::value, t1 = can_self_assign_t<T1>::value, x = t0&&t1 };
2435     using type = std::integral_constant<bool, x>;
2436 };
2437 
2438 template<>
2439 struct can_self_assign<std::tuple<>>
2440 {
2441     using type = std::integral_constant<bool, true>;
2442 };
2443 template<typename T0, typename...Ts>
2444 struct can_self_assign<std::tuple<T0, Ts...>>
2445 {
2446     using type = std::integral_constant<bool, can_self_assign_t<T0>::value && can_self_assign_t<std::tuple<Ts...>>::value >;
2447 };
2448 
2449 template<class T, T v>
2450 struct reuse_container_bool_t {
2451 };
2452 using create_new_container_t = reuse_container_bool_t<bool, false>;
2453 using reuse_container_t = reuse_container_bool_t<bool, true>;
2454 
2455 template <typename Container>
2456 struct can_reuse
2457 {
2458     using dContainer = typename std::decay<Container>::type;
2459     using can_assign = can_self_assign_t<typename dContainer::value_type>;
2460     using cannot_reuse = std::is_lvalue_reference<Container>;
2461     using value = reuse_container_bool_t<bool, can_assign::value && !cannot_reuse::value>;
2462 };
2463 
2464 template<typename Container>
2465 using can_reuse_v = typename can_reuse<Container>::value;
2466 
2467 template <typename T>
2468 struct remove_const_and_ref
2469 {
2470     using type = typename std::remove_const<typename std::remove_reference<T>::type>::type;
2471 };
2472 
2473 template<typename T>
2474 using remove_const_and_ref_t = typename remove_const_and_ref<T>::type;
2475 
2476 
2477 } // namespace internal
2478 
2479 } // namespace fplus
2480 
2481 //
2482 // maybe.hpp
2483 //
2484 
2485 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
2486 // https://github.com/Dobiasd/FunctionalPlus
2487 // Distributed under the Boost Software License, Version 1.0.
2488 // (See accompanying file LICENSE_1_0.txt or copy at
2489 //  http://www.boost.org/LICENSE_1_0.txt)
2490 
2491 
2492 
2493 #include <cassert>
2494 #include <exception>
2495 #include <functional>
2496 #include <memory>
2497 
2498 namespace fplus
2499 {
2500 
2501 // Can hold a value of type T or nothing.
2502 template <typename T>
2503 class maybe
2504 {
2505 public:
is_just() const2506     bool is_just() const { return is_present_; }
is_nothing() const2507     bool is_nothing() const { return !is_just(); }
unsafe_get_just() const2508     const T& unsafe_get_just() const
2509     {
2510         assert(is_just());
2511         return *reinterpret_cast<const T*>(&value_);
2512     }
unsafe_get_just()2513     T& unsafe_get_just()
2514     {
2515         assert(is_just());
2516         return *reinterpret_cast<T*>(&value_);
2517     }
2518     typedef T type;
maybe()2519     maybe() : is_present_(false), value_() {};
~maybe()2520     ~maybe()
2521     {
2522         destruct_content();
2523     }
maybe(const T & val_just)2524     maybe(const T& val_just) : is_present_(true), value_()
2525     {
2526         new (&value_) T(val_just);
2527     }
maybe(T && val_just)2528     maybe(T&& val_just) : is_present_(true), value_() {
2529         new (&value_) T(std::move(val_just));
2530     }
maybe(const maybe<T> & other)2531     maybe(const maybe<T>& other) : is_present_(other.is_just()), value_()
2532     {
2533         if (is_present_)
2534         {
2535             new (&value_) T(other.unsafe_get_just());
2536         }
2537     }
maybe(maybe<T> && other)2538     maybe(maybe<T>&& other) : is_present_(std::move(other.is_present_)), value_()
2539     {
2540         if (is_present_)
2541         {
2542             new (&value_) T(std::move(other.unsafe_get_just()));
2543         }
2544     }
operator =(const T & other)2545     maybe<T>& operator = (const T& other)
2546     {
2547         destruct_content();
2548         is_present_ = true;
2549         new (&value_) T(other);
2550         return *this;
2551     }
operator =(T && other)2552     maybe& operator = (T&& other) {
2553         destruct_content();
2554         is_present_ = true;
2555         new (&value_) T(std::move(other));
2556         return *this;
2557     }
operator =(const maybe<T> & other)2558     maybe<T>& operator = (const maybe<T>& other)
2559     {
2560         destruct_content();
2561         if (other.is_just())
2562         {
2563             is_present_ = true;
2564             new (&value_) T(other.unsafe_get_just());
2565         }
2566         return *this;
2567     }
operator =(maybe<T> && other)2568     maybe& operator = (maybe<T>&& other) {
2569         destruct_content();
2570         is_present_ = std::move(other.is_present_);
2571         if (is_present_)
2572         {
2573             new (&value_) T(std::move(other.unsafe_get_just()));
2574         }
2575         return *this;
2576     }
2577 private:
destruct_content()2578     void destruct_content()
2579     {
2580         if (is_present_)
2581         {
2582             is_present_ = false;
2583             (*reinterpret_cast<const T*>(&value_)).~T();
2584         }
2585     }
2586     bool is_present_;
2587     typename std::aligned_storage<sizeof(T), alignof(T)>::type value_;
2588 };
2589 
2590 namespace internal
2591 {
2592 template <typename>
2593 struct is_maybe : std::false_type
2594 {
2595 };
2596 
2597 template <typename T>
2598 struct is_maybe<maybe<T>> : std::true_type
2599 {
2600 };
2601 }
2602 
2603 // API search type: is_just : Maybe a -> Bool
2604 // fwd bind count: 0
2605 // Is not nothing?
2606 template <typename T>
is_just(const maybe<T> & maybe)2607 bool is_just(const maybe<T>& maybe)
2608 {
2609     return maybe.is_just();
2610 }
2611 
2612 // API search type: is_nothing : Maybe a -> Bool
2613 // fwd bind count: 0
2614 // Has no value?
2615 template <typename T>
is_nothing(const maybe<T> & maybe)2616 bool is_nothing(const maybe<T>& maybe)
2617 {
2618     return !is_just(maybe);
2619 }
2620 
2621 // API search type: unsafe_get_just : Maybe a -> a
2622 // fwd bind count: 0
2623 // Crashes if maybe is nothing!
2624 template <typename T>
unsafe_get_just(const maybe<T> & maybe)2625 T unsafe_get_just(const maybe<T>& maybe)
2626 {
2627     return maybe.unsafe_get_just();
2628 }
2629 
2630 // API search type: just_with_default : (a, Maybe a) -> a
2631 // fwd bind count: 0
2632 // Get the value from a maybe or the default in case it is nothing.
2633 template <typename T>
just_with_default(const T & defaultValue,const maybe<T> & maybe)2634 T just_with_default(const T& defaultValue, const maybe<T>& maybe)
2635 {
2636     if (is_just(maybe))
2637         return unsafe_get_just(maybe);
2638     return defaultValue;
2639 }
2640 
2641 // API search type: throw_on_nothing : (e, Maybe a) -> a
2642 // fwd bind count: 1
2643 // Throw exception if nothing. Return value if just.
2644 template <typename E, typename T>
throw_on_nothing(const E & e,const maybe<T> & maybe)2645 T throw_on_nothing(const E& e, const maybe<T>& maybe)
2646 {
2647     if (is_nothing(maybe))
2648         throw e;
2649     return unsafe_get_just(maybe);
2650 }
2651 
2652 // API search type: just : a -> Maybe a
2653 // fwd bind count: 0
2654 // Wrap a value in a Maybe as a Just.
2655 template <typename T>
just(const T & val)2656 maybe<T> just(const T& val)
2657 {
2658     return val;
2659 }
2660 
2661 // API search type: as_just_if : ((a -> bool), a) -> Maybe a
2662 // fwd bind count: 1
2663 // Wrap a value in a Maybe as a Just if the given predicate is fulfilled.
2664 // Otherwise a nothing is returned.
2665 template <typename Pred, typename T>
as_just_if(Pred pred,const T & val)2666 maybe<T> as_just_if(Pred pred, const T& val)
2667 {
2668     internal::check_unary_predicate_for_type<Pred, T>();
2669     if (pred(val))
2670         return val;
2671     else
2672         return {};
2673 }
2674 
2675 // API search type: maybe_to_seq : Maybe a -> [a]
2676 // fwd bind count: 0
2677 // Converts a maybe to a sequence.
2678 // singleton_seq(Just 3) == [3]
2679 // singleton_seq(Nothing) == []
2680 template <typename T, typename ContainerOut = std::vector<T>>
maybe_to_seq(const maybe<T> & maybe)2681 ContainerOut maybe_to_seq(const maybe<T>& maybe)
2682 {
2683     if (is_just(maybe))
2684         return ContainerOut(1, unsafe_get_just(maybe));
2685     return {};
2686 }
2687 
2688 // API search type: singleton_seq_as_maybe : [a] -> Maybe a
2689 // fwd bind count: 0
2690 // Converts a sequence to a maybe.
2691 // singleton_seq([]) == Nothing
2692 // singleton_seq([3]) == Just 3
2693 // singleton_seq([3,4]) == Nothing
2694 template <typename Container>
2695 maybe<typename Container::value_type>
singleton_seq_as_maybe(const Container & xs)2696 singleton_seq_as_maybe(const Container& xs)
2697 {
2698     if (xs.size() == 1)
2699         return xs.front();
2700     return {};
2701 }
2702 
2703 // API search type: nothing : () -> Maybe a
2704 // Construct a nothing of a certain Maybe type.
2705 template <typename T>
nothing()2706 maybe<T> nothing()
2707 {
2708     return {};
2709 }
2710 
2711 // True if just values are the same or if both are nothing.
2712 template <typename T>
operator ==(const maybe<T> & x,const maybe<T> & y)2713 bool operator == (const maybe<T>& x, const maybe<T>& y)
2714 {
2715     if (is_just(x) && is_just(y))
2716         return unsafe_get_just(x) == unsafe_get_just(y);
2717     return is_just(x) == is_just(y);
2718 }
2719 
2720 // False if just values are the same or if both are nothing.
2721 template <typename T>
operator !=(const maybe<T> & x,const maybe<T> & y)2722 bool operator != (const maybe<T>& x, const maybe<T>& y)
2723 {
2724     return !(x == y);
2725 }
2726 
2727 // API search type: lift_maybe : ((a -> b), Maybe a) -> Maybe b
2728 // fwd bind count: 1
2729 // Lifts a function into the maybe functor.
2730 // A function that for example was able to convert and int into a string,
2731 // now can convert a Maybe<int> into a Maybe<string>.
2732 // A nothing remains a nothing, regardless of the conversion.
2733 template <typename F, typename A>
lift_maybe(F f,const maybe<A> & m)2734 auto lift_maybe(F f, const maybe<A>& m)
2735 {
2736     internal::trigger_static_asserts<internal::check_arity_tag, F, A>();
2737 
2738     using B = std::decay_t<internal::invoke_result_t<F, A>>;
2739     if (is_just(m))
2740         return just<B>(internal::invoke(f, unsafe_get_just(m)));
2741     return nothing<B>();
2742 }
2743 
2744 // API search type: lift_maybe_def : (b, (a -> b), Maybe a) -> b
2745 // fwd bind count: 2
2746 // lift_maybe_def takes a default value and a function.
2747 // It returns a function taking a Maybe value.
2748 // This function returns the default value if the Maybe value is nothing.
2749 // Otherwise it applies the function to the value inside the Just
2750 // of the Maybe value and returns the result of this application.
2751 template <typename F, typename A, typename Default>
lift_maybe_def(const Default & def,F f,const maybe<A> & m)2752 auto lift_maybe_def(const Default& def, F f, const maybe<A>& m)
2753 {
2754     internal::trigger_static_asserts<internal::check_arity_tag, F, A>();
2755 
2756     using B = std::decay_t<internal::invoke_result_t<F, A>>;
2757     static_assert(
2758         std::is_convertible<Default, B>::value,
2759         "Default value must be convertible to Function's return type");
2760     if (is_just(m))
2761         return B(internal::invoke(f, unsafe_get_just(m)));
2762     return B(def);
2763 }
2764 
2765 // API search type: lift_maybe_2 : (((a, b) -> c), Maybe a, Maybe b) -> Maybe c
2766 // fwd bind count: 2
2767 // Lifts a binary function into the maybe functor.
2768 // Applies the function only if both arguments are justs.
2769 // Otherwise returns a nothing.
2770 template <typename F, typename A, typename B>
lift_maybe_2(F f,const maybe<A> & m_a,const maybe<B> & m_b)2771 auto lift_maybe_2(F f, const maybe<A>& m_a, const maybe<B>& m_b)
2772 {
2773     internal::trigger_static_asserts<internal::check_arity_tag, F, A, B>();
2774 
2775     using FOut = std::decay_t<internal::invoke_result_t<F, A, B>>;
2776     if (is_just(m_a) && is_just(m_b))
2777     {
2778         return just<FOut>(
2779             internal::invoke(f, unsafe_get_just(m_a), unsafe_get_just(m_b)));
2780     }
2781     return nothing<FOut>();
2782 }
2783 
2784 // API search type: lift_maybe_2_def : (c, ((a, b) -> c), Maybe a, Maybe b) -> c
2785 // fwd bind count: 3
2786 // lift_maybe_2_def takes a default value and a binary function.
2787 // It returns a function taking a two Maybe values.
2788 // This function returns the default value at least one of the
2789 // Maybe values is nothing.
2790 // Otherwise it applies the function to the two values inside the Justs
2791 // and returns the result of this application.
2792 template <typename F, typename A, typename B, typename Default>
lift_maybe_2_def(const Default & def,F f,const maybe<A> & m_a,const maybe<B> & m_b)2793 auto lift_maybe_2_def(const Default& def,
2794                       F f,
2795                       const maybe<A>& m_a,
2796                       const maybe<B>& m_b)
2797 {
2798     internal::trigger_static_asserts<internal::check_arity_tag, F, A, B>();
2799 
2800     using C = std::decay_t<internal::invoke_result_t<F, A, B>>;
2801     static_assert(
2802         std::is_convertible<Default, C>::value,
2803         "Default value must be convertible to Function's return type");
2804     if (is_just(m_a) && is_just(m_b))
2805         return C(internal::invoke(f, unsafe_get_just(m_a), unsafe_get_just(m_b)));
2806     return C(def);
2807 }
2808 
2809 // API search type: join_maybe : Maybe Maybe a -> Maybe a
2810 // Flattens a nested maybe.
2811 // join_maybe(Just Just x) == Just x
2812 // join_maybe(Just Nothing) == Nothing
2813 // join_maybe(Nothing) == Nothing
2814 template <typename A>
join_maybe(const maybe<maybe<A>> & m)2815 maybe<A> join_maybe(const maybe<maybe<A>>& m)
2816 {
2817     if (is_just(m))
2818         return unsafe_get_just(m);
2819     else
2820         return nothing<A>();
2821 }
2822 
2823 // API search type: and_then_maybe : ((a -> Maybe b), (Maybe a)) -> Maybe b
2824 // fwd bind count: 1
2825 // Monadic bind.
2826 // Returns nothing if the maybe already is nothing.
2827 // Otherwise return the result of applying
2828 // the function to the just value of the maybe.
2829 template <typename T, typename F>
and_then_maybe(F f,const maybe<T> & m)2830 auto and_then_maybe(F f, const maybe<T>& m)
2831 {
2832     internal::trigger_static_asserts<internal::check_arity_tag, F, T>();
2833     using FOut = std::decay_t<internal::invoke_result_t<F, T>>;
2834     static_assert(internal::is_maybe<FOut>::value,
2835                   "Function must return a maybe<> type");
2836     if (is_just(m))
2837         return internal::invoke(f, unsafe_get_just(m));
2838     else
2839         return nothing<typename FOut::type>();
2840 }
2841 
2842 // API search type: compose_maybe : ((a -> Maybe b), (b -> Maybe c)) -> (a -> Maybe c)
2843 // Left-to-right Kleisli composition of monads.
2844 // Composes multiple callables taking a value and returning Maybe.
2845 // If the first callable returns a just, the value from the just
2846 // is extracted and shoved into the next callable.
2847 // If the first callable returns a nothing, it remains a nothing.
2848 // The first callable can take a variadic number of parameters.
2849 template <typename... Callables>
compose_maybe(Callables &&...callables)2850 auto compose_maybe(Callables&&... callables)
2851 {
2852     auto bind_maybe = [](auto f, auto g) {
2853         // next step would be to perfectly forward callables, as shown here:
2854         // https://vittorioromeo.info/index/blog/capturing_perfectly_forwarded_objects_in_lambdas.html
2855         return [f = std::move(f), g = std::move(g)](auto&&... args)
2856         {
2857             using FOut = std::decay_t<
2858                 internal::invoke_result_t<decltype(f), decltype(args)...>>;
2859             static_assert(internal::is_maybe<FOut>::value,
2860                           "Functions must return a maybe<> type");
2861             using GOut = std::decay_t<
2862                 internal::invoke_result_t<decltype(g), typename FOut::type>>;
2863             static_assert(internal::is_maybe<GOut>::value,
2864                           "Functions must return a maybe<> type");
2865 
2866             auto maybeB =
2867                 internal::invoke(f, std::forward<decltype(args)>(args)...);
2868             if (is_just(maybeB))
2869                 return internal::invoke(g, unsafe_get_just(maybeB));
2870             return GOut{};
2871         };
2872     };
2873 
2874     return internal::compose_binary_lift(bind_maybe,
2875                                        std::forward<Callables>(callables)...);
2876 }
2877 
2878 // API search type: flatten_maybe : (Maybe (Maybe a)) -> Maybe a
2879 // fwd bind count: 0
2880 // Also known as join.
2881 template <typename T>
flatten_maybe(const maybe<maybe<T>> & maybe_maybe)2882 maybe<T> flatten_maybe(const maybe<maybe<T>>& maybe_maybe)
2883 {
2884     if (is_nothing(maybe_maybe))
2885         return nothing<T>();
2886     return unsafe_get_just(maybe_maybe);
2887 }
2888 
2889 } // namespace fplus
2890 
2891 
2892 //
2893 // internal/container_common.hpp
2894 //
2895 
2896 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
2897 // https://github.com/Dobiasd/FunctionalPlus
2898 // Distributed under the Boost Software License, Version 1.0.
2899 // (See accompanying file LICENSE_1_0.txt or copy at
2900 //  http://www.boost.org/LICENSE_1_0.txt)
2901 
2902 
2903 #include <numeric>
2904 #include <type_traits>
2905 
2906 
2907 namespace fplus
2908 {
2909 namespace internal
2910 {
2911 
2912 template<class InputIt, class T>
accumulate(InputIt first,InputIt last,T init)2913 T accumulate(InputIt first, InputIt last, T init)
2914 {
2915     for (; first != last; ++first) {
2916         init = std::move(init) + *first;
2917     }
2918     return init;
2919 }
2920 
2921 template<class InputIt, class T, class BinaryOperation>
2922 T accumulate(InputIt first, InputIt last, T init,
2923              BinaryOperation op)
2924 {
2925     for (; first != last; ++first) {
2926         init = op(std::move(init), *first);
2927     }
2928     return init;
2929 }
2930 
2931 template <typename F,
2932           typename Acc,
2933           typename InputIterator,
2934           typename OutputIterator>
scan_impl(F f,const Acc & init,OutputIterator itOut,InputIterator begin,InputIterator end)2935 void scan_impl(F f,
2936                const Acc& init,
2937                OutputIterator itOut,
2938                InputIterator begin,
2939                InputIterator end)
2940 {
2941     *itOut = init;
2942 
2943     auto g = [itOut, f](auto acc, auto x) mutable
2944     {
2945         acc = internal::invoke(f, acc, x);
2946         *itOut = acc;
2947         return acc;
2948     };
2949 
2950     internal::accumulate(begin, end, init, g);
2951 }
2952 }
2953 }
2954 
2955 #include <algorithm>
2956 #include <cassert>
2957 #include <cmath>
2958 #include <cstddef>
2959 #include <iterator>
2960 #include <numeric>
2961 
2962 namespace fplus
2963 {
2964 
2965 namespace internal
2966 {
2967     template <typename UnaryPredicate, typename Container>
check_unary_predicate_for_container()2968     void check_unary_predicate_for_container()
2969     {
2970         internal::check_unary_predicate_for_type<UnaryPredicate,
2971             typename Container::value_type>();
2972     }
2973 
2974     template <typename F, typename Container>
check_index_with_type_predicate_for_container()2975     void check_index_with_type_predicate_for_container()
2976     {
2977         typedef typename Container::value_type T;
2978         internal::trigger_static_asserts<internal::binary_function_tag, F, std::size_t, T>();
2979         static_assert(std::is_convertible<
2980             internal::invoke_result_t<F, std::size_t, T>, bool>::value,
2981             "Function must return bool.");
2982     }
2983 
2984     template <typename Compare, typename Container>
check_compare_for_container()2985     void check_compare_for_container()
2986     {
2987         typedef typename Container::value_type T;
2988         internal::trigger_static_asserts<internal::binary_predicate_tag, Compare, T, T>();
2989     }
2990 
2991     template <typename BinaryPredicate, typename Container>
check_binary_predicate_for_container()2992     void check_binary_predicate_for_container()
2993     {
2994         typedef typename Container::value_type T;
2995         internal::trigger_static_asserts<internal::binary_predicate_tag, BinaryPredicate, T, T>();
2996     }
2997 
2998     // PrepareContainer and BackInserter are overloaded
2999     // to increase performance on std::vector and std::string
3000     // by using std::vector<T>::reserve
3001     // and std::back_inserter instead of std::back_inserter.
3002     // In VC2015, release mode, Celsius W520 Xeon
3003     // this leads to an increase in performance of about a factor of 3
3004     // for transform.
3005     template <typename C>
prepare_container(const std::basic_string<C,std::char_traits<C>,std::allocator<C>> & ys,std::size_t size)3006     void prepare_container(const std::basic_string<C, std::char_traits<C>,
3007         std::allocator<C>>& ys, std::size_t size)
3008     {
3009         ys.reserve(size);
3010     }
3011 
3012     template <typename Y>
prepare_container(std::vector<Y> & ys,std::size_t size)3013     void prepare_container(std::vector<Y>& ys, std::size_t size)
3014     {
3015         ys.reserve(size);
3016     }
3017 
3018     template <typename T, std::size_t N>
prepare_container(std::array<T,N> &,std::size_t size)3019     void prepare_container(std::array<T, N>&, std::size_t size)
3020     {
3021         assert(size == N);
3022         unused(size);
3023     }
3024 
3025     template <typename Y>
prepare_container(std::unordered_set<Y> & ys,std::size_t size)3026     void prepare_container(std::unordered_set<Y>& ys, std::size_t size)
3027     {
3028         ys.reserve(size);
3029     }
3030 
3031     template <typename Key, typename T>
prepare_container(std::unordered_map<Key,T> & ys,std::size_t size)3032     void prepare_container(std::unordered_map<Key, T>& ys, std::size_t size)
3033     {
3034         ys.reserve(size);
3035     }
3036 
3037     template <typename Y>
prepare_container(std::unordered_multiset<Y> & ys,std::size_t size)3038     void prepare_container(std::unordered_multiset<Y>& ys, std::size_t size)
3039     {
3040         ys.reserve(size);
3041     }
3042 
3043     template <typename Key, typename T>
prepare_container(std::unordered_multimap<Key,T> & ys,std::size_t size)3044     void prepare_container(std::unordered_multimap<Key, T>& ys, std::size_t size)
3045     {
3046         ys.reserve(size);
3047     }
3048 
3049     template <typename Container>
prepare_container(Container &,std::size_t)3050     void prepare_container(Container&, std::size_t)
3051     {
3052     }
3053 
3054     template <typename Container>
get_back_inserter(std::string & ys)3055     std::back_insert_iterator<Container> get_back_inserter(std::string& ys)
3056     {
3057         return std::back_inserter(ys);
3058     }
3059 
3060     template <typename Container, typename Y>
get_back_inserter(std::vector<Y> & ys)3061     std::back_insert_iterator<Container> get_back_inserter(std::vector<Y>& ys)
3062     {
3063         return std::back_inserter(ys);
3064     }
3065 
3066     template <typename Container, typename Y>
get_back_inserter(std::list<Y> & ys)3067     std::back_insert_iterator<Container> get_back_inserter(std::list<Y>& ys)
3068     {
3069         return std::back_inserter(ys);
3070     }
3071 
3072     template <typename Container, typename Y>
get_back_inserter(std::deque<Y> & ys)3073     std::back_insert_iterator<Container> get_back_inserter(std::deque<Y>& ys)
3074     {
3075         return std::back_inserter(ys);
3076     }
3077 
3078     // Avoid self-assignment.
3079     template <typename T>
assign(T & x,T && y)3080     void assign(T& x, T&& y) {
3081         if (&x != &y)
3082             x = std::move(y);
3083     }
3084 
3085     template <typename T, std::size_t N>
3086     struct array_back_insert_iterator : public std::back_insert_iterator<std::array<T, N>>
3087     {
3088         typedef std::back_insert_iterator<std::array<T, N>> base_type;
array_back_insert_iteratorfplus::internal::array_back_insert_iterator3089         explicit array_back_insert_iterator(std::array<T, N>& arr) :
3090             base_type(arr), arr_ptr_(&arr), pos_(0) {}
array_back_insert_iteratorfplus::internal::array_back_insert_iterator3091         array_back_insert_iterator(const array_back_insert_iterator<T, N>& other) :
3092             base_type(*other.arr_ptr_), arr_ptr_(other.arr_ptr_), pos_(other.pos_) {}
operator =fplus::internal::array_back_insert_iterator3093         array_back_insert_iterator<T, N>& operator=(const array_back_insert_iterator<T, N>& other)
3094         {
3095             arr_ptr_ = other.arr_ptr_;
3096             pos_ = other.pos_;
3097             return *this;
3098         }
~array_back_insert_iteratorfplus::internal::array_back_insert_iterator3099         ~array_back_insert_iterator()
3100         {
3101             assert(pos_ == 0 || pos_ == N);
3102         }
operator =fplus::internal::array_back_insert_iterator3103         array_back_insert_iterator<T, N>& operator=(const T& x)
3104         {
3105             assert(pos_ < N);
3106             (*arr_ptr_)[pos_] = x;
3107             ++pos_;
3108             return *this;
3109         }
operator =fplus::internal::array_back_insert_iterator3110         array_back_insert_iterator<T, N>& operator=(T&& x)
3111         {
3112             assert(pos_ < N);
3113             assign((*arr_ptr_)[pos_], std::move(x));
3114             ++pos_;
3115             return *this;
3116         }
operator *fplus::internal::array_back_insert_iterator3117         array_back_insert_iterator<T, N>& operator*() { return *this; }
operator ++fplus::internal::array_back_insert_iterator3118         array_back_insert_iterator<T, N>& operator++() { return *this; }
operator ++fplus::internal::array_back_insert_iterator3119         array_back_insert_iterator<T, N> operator++(int) { return *this; }
3120     private:
3121         std::array<T, N>* arr_ptr_;
3122         std::size_t pos_;
3123     };
3124 
3125 #if defined(_MSC_VER) && _MSC_VER >= 1900
3126     template <typename T, std::size_t N>
3127     struct std::_Is_checked_helper<array_back_insert_iterator<T, N>>
3128         : public true_type
3129     { // mark array_back_insert_iterator as checked
3130     };
3131 #endif
3132 
3133     template <typename Container, typename Y, std::size_t N>
get_back_inserter(std::array<Y,N> & ys)3134     array_back_insert_iterator<Y, N> get_back_inserter(std::array<Y, N>& ys)
3135     {
3136         return array_back_insert_iterator<Y, N>(ys);
3137     }
3138 
3139     template <typename Container>
get_back_inserter(Container & ys)3140     std::insert_iterator<Container> get_back_inserter(Container& ys)
3141     {
3142         return std::inserter(ys, std::end(ys));
3143     }
3144 
3145     template <typename Iterator>
advance_iterator(Iterator & it,std::size_t distance)3146     void advance_iterator(Iterator& it, std::size_t distance)
3147     {
3148         std::advance(it,
3149             static_cast<typename Iterator::difference_type>(distance));
3150     }
3151 
3152     template <typename T>
advance_iterator(T * & it,std::size_t distance)3153     void advance_iterator(T*& it, std::size_t distance)
3154     {
3155         it += static_cast<std::ptrdiff_t>(distance);
3156     }
3157 
3158     template <typename Iterator>
add_to_iterator(Iterator it,std::size_t distance=1)3159     Iterator add_to_iterator(Iterator it, std::size_t distance = 1)
3160     {
3161         return std::next(it,
3162             static_cast<typename Iterator::difference_type>(distance));
3163     }
3164 
3165     // GCC 4.9 does not support std::rbegin, std::rend and std::make_reverse_iterator
3166     template <typename Iterator>
make_reverse_iterator(Iterator it)3167     std::reverse_iterator<Iterator> make_reverse_iterator(Iterator it)
3168     {
3169         return std::reverse_iterator<Iterator>(it);
3170     }
3171 } // namespace internal
3172 
3173 // API search type: is_even : Int -> Bool
3174 // fwd bind count: 0
3175 // Checks if x is even.
3176 template <typename X>
is_even(X x)3177 bool is_even(X x)
3178 {
3179     static_assert(std::is_integral<X>::value, "type must be integral");
3180     return x % 2 == 0;
3181 }
3182 
3183 // API search type: is_odd : Int -> Bool
3184 // fwd bind count: 0
3185 // Checks if x is odd.
3186 template <typename X>
is_odd(X x)3187 bool is_odd(X x)
3188 {
3189     static_assert(std::is_integral<X>::value, "type must be integral");
3190     return x % 2 != 0;
3191 }
3192 
3193 // API search type: is_empty : [a] -> Bool
3194 // fwd bind count: 0
3195 // Returns true if the container holds no elements.
3196 // is_empty([1, 2]) == false
3197 // is_empty([]) == true
3198 template <typename Container>
is_empty(const Container & xs)3199 bool is_empty(const Container& xs)
3200 {
3201     return xs.empty();
3202 }
3203 
3204 // API search type: is_not_empty : [a] -> Bool
3205 // fwd bind count: 0
3206 // Returns true if the container holds at least one element.
3207 // is_not_empty([1, 2]) == true
3208 template <typename Container>
is_not_empty(const Container & xs)3209 bool is_not_empty(const Container& xs)
3210 {
3211     return !is_empty(xs);
3212 }
3213 
3214 // API search type: size_of_cont : [a] -> Int
3215 // fwd bind count: 0
3216 // Returns the number of elements in the given container.
3217 // size_of_cont([3, 4]) == 2
3218 template <typename Container>
size_of_cont(const Container & xs)3219 std::size_t size_of_cont(const Container& xs)
3220 {
3221     return xs.size();
3222 }
3223 
3224 // API search type: convert : a -> b
3225 // fwd bind count: 0
3226 // Converts one type of element into another.
3227 template <typename Dest, typename Source>
3228 Dest convert(const Source& x)
3229 {
3230     return Dest(x);
3231 }
3232 
3233 // API search type: convert_elems : [a] -> [b]
3234 // fwd bind count: 0
3235 // Converts all elements in a sequence to a different type.
3236 // convert_elems<NewT>([1, 2, 3]) == [NewT(1), NewT(2), NewT(3)]
3237 template <typename NewT, typename ContainerIn,
3238     typename ContainerOut = typename internal::same_cont_new_t<ContainerIn, NewT, 0>::type>
convert_elems(const ContainerIn & xs)3239 ContainerOut convert_elems(const ContainerIn& xs)
3240 {
3241     static_assert(std::is_constructible<NewT,
3242         typename ContainerIn::value_type>::value,
3243         "Elements not convertible.");
3244     ContainerOut ys;
3245     internal::prepare_container(ys, size_of_cont(xs));
3246     auto it = internal::get_back_inserter<ContainerOut>(ys);
3247     // using 'for (const auto& x ...)' is even for ints as fast as
3248     // using 'for (int x ...)' (GCC, O3), so there is no need to
3249     // check if the type is fundamental and then dispatch accordingly.
3250     for (const auto& x : xs)
3251     {
3252         *it = convert<NewT>(x);
3253     }
3254     return ys;
3255 }
3256 
3257 // API search type: convert_container : [a] -> [a]
3258 // fwd bind count: 0
3259 // Change the type of the container
3260 // while keeping the elements in the sequence the same.
3261 // convert_container([1, 2, 3]) == [1, 2, 3]
3262 // Useful for example if you want to convert an std::list to an std::vector.
3263 template <typename ContainerOut, typename ContainerIn>
3264 ContainerOut convert_container(const ContainerIn& xs)
3265 {
3266     typedef typename ContainerIn::value_type SourceElem;
3267     typedef typename ContainerOut::value_type DestElem;
3268     static_assert(std::is_same<DestElem, SourceElem>::value,
3269         "Source and dest container must have the same value_type");
3270     ContainerOut ys;
3271     internal::prepare_container(ys, size_of_cont(xs));
3272     auto itOut = internal::get_back_inserter<ContainerOut>(ys);
3273     std::copy(std::begin(xs), std::end(xs), itOut);
3274     return ys;
3275 }
3276 
3277 // API search type: convert_container_and_elems : [a] -> [b]
3278 // fwd bind count: 0
3279 // Converts between different containers and elements.
3280 // Dest elements are allowed to have explicit constructors.
3281 // convert([1, 2, 3]) == [1, 2, 3]
3282 template <typename ContainerOut, typename ContainerIn>
3283 ContainerOut convert_container_and_elems(const ContainerIn& xs)
3284 {
3285     static_assert(std::is_convertible<typename ContainerIn::value_type,
3286         typename ContainerOut::value_type>::value,
3287         "Elements not convertible.");
3288     typedef typename ContainerOut::value_type DestElem;
3289     ContainerOut ys;
3290     internal::prepare_container(ys, size_of_cont(xs));
3291     auto it = internal::get_back_inserter<ContainerOut>(ys);
3292     for (const auto& x : xs)
3293     {
3294         *it = convert<DestElem>(x);
3295     }
3296     return ys;
3297 }
3298 
3299 namespace internal
3300 {
3301 
3302 template <typename Container>
get_segment(internal::reuse_container_t,std::size_t idx_begin,std::size_t idx_end,Container && xs)3303 Container get_segment(internal::reuse_container_t,
3304     std::size_t idx_begin, std::size_t idx_end, Container&& xs)
3305 {
3306     idx_end = std::min(idx_end, size_of_cont(xs));
3307     if (idx_end <= idx_begin)
3308     {
3309         xs.clear();
3310         return std::forward<Container>(xs);
3311     }
3312     auto itBegin = std::begin(xs);
3313     internal::advance_iterator(itBegin, idx_begin);
3314     auto itEnd = itBegin;
3315     internal::advance_iterator(itEnd, idx_end - idx_begin);
3316     xs.erase(std::copy(itBegin, itEnd, std::begin(xs)), std::end(xs));
3317     return std::forward<Container>(xs);
3318 }
3319 
3320 template <typename Container>
get_segment(internal::create_new_container_t,std::size_t idx_begin,std::size_t idx_end,const Container & xs)3321 Container get_segment(internal::create_new_container_t,
3322     std::size_t idx_begin, std::size_t idx_end, const Container& xs)
3323 {
3324     idx_end = std::min(idx_end, size_of_cont(xs));
3325     if (idx_end <= idx_begin)
3326     {
3327         return {};
3328     }
3329     Container result;
3330     auto itBegin = std::begin(xs);
3331     internal::advance_iterator(itBegin, idx_begin);
3332     auto itEnd = itBegin;
3333     internal::advance_iterator(itEnd, idx_end - idx_begin);
3334     std::copy(itBegin, itEnd, internal::get_back_inserter(result));
3335     return result;
3336 }
3337 
3338 } // namespace internal
3339 
3340 // API search type: get_segment : (Int, Int, [a]) -> [a]
3341 // fwd bind count: 2
3342 // Return a defined segment from the sequence.
3343 // get_segment(2, 5, [0,1,2,3,4,5,6,7,8]) == [2,3,4]
3344 // get_segment(2, 15, [0,1,2,3,4,5,6,7,8]) == [2,3,4,5,6,7,8]
3345 // get_segment(5, 2, [0,1,2,3,4,5,6,7,8]) == []
3346 // Also known as slice.
3347 template <typename Container,
3348     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
get_segment(std::size_t idx_begin,std::size_t idx_end,Container && xs)3349 ContainerOut get_segment
3350         (std::size_t idx_begin, std::size_t idx_end, Container&& xs)
3351 {
3352     return internal::get_segment(internal::can_reuse_v<Container>{},
3353         idx_begin, idx_end, std::forward<Container>(xs));
3354 }
3355 
3356 namespace internal
3357 {
3358 
3359 template <typename ContainerToken, typename Container>
set_segment(internal::reuse_container_t,std::size_t idx_begin,const ContainerToken & token,Container && xs)3360 Container set_segment(internal::reuse_container_t,
3361     std::size_t idx_begin, const ContainerToken& token, Container&& xs)
3362 {
3363     assert(idx_begin + size_of_cont(token) < size_of_cont(xs));
3364     auto itBegin = std::begin(xs);
3365     internal::advance_iterator(itBegin, idx_begin);
3366     std::copy(std::begin(token), std::end(token), itBegin);
3367     return std::forward<Container>(xs);
3368 }
3369 
3370 template <typename ContainerToken, typename Container>
set_segment(internal::create_new_container_t,std::size_t idx_begin,const ContainerToken & token,const Container & xs)3371 Container set_segment(internal::create_new_container_t,
3372     std::size_t idx_begin, const ContainerToken& token, const Container& xs)
3373 {
3374     Container result = xs;
3375     return set_segment(internal::reuse_container_t(),
3376         idx_begin, token, std::move(result));
3377 }
3378 
3379 } // namespace internal
3380 
3381 // API search type: set_segment : (Int, [a], [a]) -> [a]
3382 // fwd bind count: 2
3383 // Replace part of a sequence with a token.
3384 // set_segment(2, [9,9,9], [0,1,2,3,4,5,6,7,8]) == [0,1,9,9,9,5,6,7,8]
3385 // Crashes on invalid indices.
3386 // Also known as replace_segment.
3387 template <typename ContainerToken, typename Container,
3388     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
set_segment(std::size_t idx_begin,const ContainerToken & token,Container && xs)3389 ContainerOut set_segment
3390         (std::size_t idx_begin, const ContainerToken& token, Container&& xs)
3391 {
3392     return internal::set_segment(internal::can_reuse_v<Container>{},
3393         idx_begin, token, std::forward<Container>(xs));
3394 }
3395 
3396 namespace internal
3397 {
3398 
3399 template <typename Container>
remove_segment(internal::reuse_container_t,std::size_t idx_begin,std::size_t idx_end,Container && xs)3400 Container remove_segment(internal::reuse_container_t,
3401     std::size_t idx_begin, std::size_t idx_end, Container&& xs)
3402 {
3403     assert(idx_begin <= idx_end);
3404     assert(idx_end <= size_of_cont(xs));
3405 
3406     auto firstBreakIt = std::begin(xs);
3407     internal::advance_iterator(firstBreakIt, idx_begin);
3408 
3409     auto secondBreakIt = std::begin(xs);
3410     internal::advance_iterator(secondBreakIt, idx_end);
3411 
3412     xs.erase(
3413         std::copy(secondBreakIt, std::end(xs), firstBreakIt), std::end(xs));
3414     return std::forward<Container>(xs);
3415 }
3416 
3417 template <typename Container>
remove_segment(internal::create_new_container_t,std::size_t idx_begin,std::size_t idx_end,const Container & xs)3418 Container remove_segment(internal::create_new_container_t,
3419     std::size_t idx_begin, std::size_t idx_end, const Container& xs)
3420 {
3421     assert(idx_begin <= idx_end);
3422     assert(idx_end <= size_of_cont(xs));
3423 
3424     Container result;
3425     std::size_t length = idx_end - idx_begin;
3426     internal::prepare_container(result, size_of_cont(xs) - length);
3427 
3428     auto firstBreakIt = std::begin(xs);
3429     internal::advance_iterator(firstBreakIt, idx_begin);
3430     std::copy(std::begin(xs), firstBreakIt, internal::get_back_inserter(result));
3431 
3432     auto secondBreakIt = std::begin(xs);
3433     internal::advance_iterator(secondBreakIt, idx_end);
3434     std::copy(secondBreakIt, std::end(xs), internal::get_back_inserter(result));
3435 
3436     return result;
3437 }
3438 
3439 } // namespace internal
3440 
3441 // API search type: remove_segment : (Int, Int, [a]) -> [a]
3442 // fwd bind count: 2
3443 // Cuts our a  defined segment from the sequence.
3444 // remove_segment(2, 5, [0,1,2,3,4,5,6,7]) == [0,1,5,6,7]
3445 // crashes on invalid indices
3446 template <typename Container,
3447     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
remove_segment(std::size_t idx_begin,std::size_t idx_end,Container && xs)3448 ContainerOut remove_segment(
3449         std::size_t idx_begin, std::size_t idx_end, Container&& xs)
3450 {
3451     return internal::remove_segment(internal::can_reuse_v<Container>{},
3452         idx_begin, idx_end, std::forward<Container>(xs));
3453 }
3454 
3455 // API search type: insert_at : (Int, [a], [a]) -> [a]
3456 // fwd bind count: 2
3457 // Inserts a token into a sequence at a specific position.
3458 // insert_at(2, [8,9], [0,1,2,3,4]) == [0,1,8,9,2,3,4]
3459 // Unsafe! Crashes on invalid index.
3460 template <typename Container>
insert_at(std::size_t idx_begin,const Container & token,const Container & xs)3461 Container insert_at(std::size_t idx_begin,
3462         const Container& token, const Container& xs)
3463 {
3464     assert(idx_begin <= size_of_cont(xs));
3465 
3466     Container result;
3467     internal::prepare_container(result, size_of_cont(xs) + size_of_cont(token));
3468 
3469     auto breakIt = std::begin(xs);
3470     internal::advance_iterator(breakIt, idx_begin);
3471     std::copy(std::begin(xs), breakIt, internal::get_back_inserter(result));
3472     std::copy(std::begin(token), std::end(token), internal::get_back_inserter(result));
3473     std::copy(breakIt, std::end(xs), internal::get_back_inserter(result));
3474 
3475     return result;
3476 }
3477 
3478 // API search type: elem_at_idx : (Int, [a]) -> a
3479 // fwd bind count: 1
3480 // Return the nth element of a sequence.
3481 // elem_at_idx(2, [7,6,5,4,3]) == 5
3482 // Unsafe! Crashes on invalid index.
3483 template <typename Container>
elem_at_idx(std::size_t idx,const Container & xs)3484 auto elem_at_idx(std::size_t idx, const Container& xs)
3485 {
3486     assert(idx < size_of_cont(xs));
3487     auto it = std::begin(xs);
3488     internal::advance_iterator(it, idx);
3489     return *it;
3490 }
3491 
3492 // API search type: elem_at_idx_maybe : (Int, [a]) -> Maybe a
3493 // fwd bind count: 1
3494 // Return the nth element of a sequence if existing.
3495 // elem_at_idx_maybe(2, [7,6,5,4,3]) == Just 5
3496 // elem_at_idx_maybe(9, [7,6,5,4,3]) == Nothing
3497 // Use elem_at_idx_or_nothing if you want to provide a signed index type.
3498 template <typename Container,
3499     typename T = typename Container::value_type>
elem_at_idx_maybe(std::size_t idx,const Container & xs)3500 maybe<T> elem_at_idx_maybe(std::size_t idx, const Container& xs)
3501 {
3502     if (size_of_cont(xs) < idx)
3503     {
3504         return {};
3505     }
3506     auto it = std::begin(xs);
3507     internal::advance_iterator(it, idx);
3508     return *it;
3509 }
3510 
3511 // API search type: elems_at_idxs : ([Int], [a]) -> [a]
3512 // fwd bind count: 1
3513 // Construct a subsequence from the elements with the given indices.
3514 // elem_at_idxs([1, 3], [7,6,5,4,3]) == [6, 4]
3515 template <typename Container,
3516     typename ContainerIdxs,
3517     typename T = typename Container::value_type,
3518     typename ContainerOut = std::vector<T>>
elems_at_idxs(const ContainerIdxs & idxs,const Container & xs)3519 std::vector<T> elems_at_idxs(const ContainerIdxs& idxs, const Container& xs)
3520 {
3521     static_assert(std::is_same<typename ContainerIdxs::value_type, std::size_t>::value,
3522         "Indices must be std::size_t");
3523     ContainerOut result;
3524     internal::prepare_container(result, size_of_cont(idxs));
3525     auto itOut = internal::get_back_inserter(result);
3526     for (std::size_t idx : idxs)
3527     {
3528         *itOut = elem_at_idx(idx, xs);
3529     }
3530     return result;
3531 }
3532 
3533 namespace internal
3534 {
3535 
3536 template <typename Container, typename F>
3537 Container transform(internal::reuse_container_t, F f, Container&& xs)
3538 {
3539     internal::trigger_static_asserts<internal::unary_function_tag,
3540                                          F,
3541                                          decltype(*std::begin(xs))>();
3542     std::transform(std::begin(xs), std::end(xs), std::begin(xs), f);
3543     return std::forward<Container>(xs);
3544 }
3545 
3546 template <typename ContainerOut, typename F, typename ContainerIn>
3547 ContainerOut transform(internal::create_new_container_t, F f,
3548     const ContainerIn& xs)
3549 {
3550     internal::trigger_static_asserts<internal::unary_function_tag,
3551                                          F,
3552                                          decltype(*std::begin(xs))>();
3553     ContainerOut ys;
3554     internal::prepare_container(ys, size_of_cont(xs));
3555     auto it = internal::get_back_inserter<ContainerOut>(ys);
3556     std::transform(std::begin(xs), std::end(xs), it, f);
3557     return ys;
3558 }
3559 
3560 } // namespace internal
3561 
3562 // API search type: transform : ((a -> b), [a]) -> [b]
3563 // fwd bind count: 1
3564 // Apply a function to every element in a sequence.
3565 // transform((*2), [1, 3, 4]) == [2, 6, 8]
3566 // Also known as map or fmap.
3567 template <typename F, typename ContainerIn,
3568     typename ContainerOut = typename internal::same_cont_new_t_from_unary_f<
3569         internal::remove_const_and_ref_t<ContainerIn>, F, 0>::type>
transform(F f,ContainerIn && xs)3570 ContainerOut transform(F f, ContainerIn&& xs)
3571 {
3572     using reuse_t = typename std::conditional<
3573         std::is_same<
3574             internal::can_reuse_v<ContainerIn>,
3575             internal::reuse_container_t>::value &&
3576         std::is_base_of<
3577             std::true_type,
3578             internal::has_order<ContainerIn>>::value &&
3579         std::is_same<
3580             internal::remove_const_and_ref_t<ContainerIn>,
3581             ContainerOut>::value,
3582         internal::reuse_container_t,
3583         internal::create_new_container_t>::type;
3584     return internal::transform<ContainerOut>(
3585         reuse_t{}, f, std::forward<ContainerIn>(xs));
3586 }
3587 
3588 // API search type: transform_convert : ((a -> b), [a]) -> [b]
3589 // fwd bind count: 1
3590 // transform_convert((*2), [1, 3, 4]) == [2, 6, 8]
3591 // Same as transform, but makes it easy to
3592 // use an output container type different from the input container type.
3593 template <typename ContainerOut, typename F, typename ContainerIn>
3594 ContainerOut transform_convert(F f, const ContainerIn& xs)
3595 {
3596     internal::trigger_static_asserts<internal::unary_function_tag, F, typename ContainerIn::value_type>();
3597     ContainerOut ys;
3598     internal::prepare_container(ys, size_of_cont(xs));
3599     auto it = internal::get_back_inserter<ContainerOut>(ys);
3600     std::transform(std::begin(xs), std::end(xs), it, f);
3601     return ys;
3602 }
3603 
3604 // API search type: transform_inner : ((a -> b), [[a]]) -> [[b]]
3605 // fwd bind count: 1
3606 // Applies a function to the elements of the inner containers
3607 // of a nested sequence.
3608 // transform_inner((*2), [[1, 3, 4], [1, 2]]) == [[2, 6, 8], [2, 4]]
3609 // Also known as transform_nested, map_nested or map_inner.
3610 template <typename F, typename ContainerIn,
3611     typename ContainerOut =
3612         typename internal::same_cont_new_t<
3613             ContainerIn,
3614             typename internal::same_cont_new_t_from_unary_f<
3615                 typename ContainerIn::value_type, F, 0
3616             >::type, 0
3617         >::type>
transform_inner(F f,const ContainerIn & xs)3618 ContainerOut transform_inner(F f, const ContainerIn& xs)
3619 {
3620     internal::trigger_static_asserts<internal::unary_function_tag, F, typename ContainerIn::value_type::value_type>();
3621     return fplus::transform(
3622         fplus::bind_1st_of_2(
3623             fplus::transform<F, const typename ContainerIn::value_type&>, f),
3624         xs);
3625 }
3626 
3627 namespace internal
3628 {
3629 
3630 template <typename Container>
reverse(internal::reuse_container_t,Container && xs)3631 Container reverse(internal::reuse_container_t, Container&& xs)
3632 {
3633     static_assert(internal::has_order<Container>::value,
3634         "Reverse: Container has no order.");
3635     std::reverse(std::begin(xs), std::end(xs));
3636     return std::forward<Container>(xs);
3637 }
3638 
3639 template <typename Container>
reverse(internal::create_new_container_t,const Container & xs)3640 Container reverse(internal::create_new_container_t, const Container& xs)
3641 {
3642     static_assert(internal::has_order<Container>::value,
3643         "Reverse: Container has no order.");
3644     Container ys = xs;
3645     std::reverse(std::begin(ys), std::end(ys));
3646     return ys;
3647 }
3648 
3649 } // namespace internal
3650 
3651 // API search type: reverse : [a] -> [a]
3652 // fwd bind count: 0
3653 // Reverse a sequence.
3654 // reverse([0,4,2,6]) == [6,2,4,0]
3655 template <typename Container,
3656     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
reverse(Container && xs)3657 ContainerOut reverse(Container&& xs)
3658 {
3659     return internal::reverse(internal::can_reuse_v<Container>{},
3660         std::forward<Container>(xs));
3661 }
3662 
3663 // API search type: take : (Int, [a]) -> [a]
3664 // fwd bind count: 1
3665 // Return the first n elements of a sequence xs.
3666 // In case n >= length(xs), xs is returned.
3667 // take(3, [0,1,2,3,4,5,6,7]) == [0,1,2]
3668 // take(10, [0,1,2]) == [0,1,2]
3669 template <typename Container,
3670     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
take(std::size_t amount,Container && xs)3671 ContainerOut take(std::size_t amount, Container&& xs)
3672 {
3673     if (amount >= size_of_cont(xs))
3674         return xs;
3675     return get_segment(0, amount, std::forward<Container>(xs));
3676 }
3677 
3678 // API search type: take_exact : (Int, [a]) -> [a]
3679 // fwd bind count: 1
3680 // Return exactly the first n elements of a sequence xs.
3681 // Unsafe! Crashes then sequence is too short.
3682 // take_exact(3, [0,1,2,3,4,5,6,7]) == [0,1,2]
3683 // take_exact(10, [0,1,2]) == crash
3684 template <typename Container,
3685     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
take_exact(std::size_t amount,Container && xs)3686 ContainerOut take_exact(std::size_t amount, Container&& xs)
3687 {
3688     return get_segment(0, amount, std::forward<Container>(xs));
3689 }
3690 
3691 // API search type: take_cyclic : (Int, [a]) -> [a]
3692 // fwd bind count: 1
3693 // Takes n elements from a sequence considering it as cyclic.
3694 // take_cyclic(5, [0,1,2,3]) == [0,1,2,3,0]
3695 // take_cyclic(7, [0,1,2,3]) == [0,1,2,3,0,1,2]
3696 // take_cyclic(7, [0,1]) == [0,1,0,1,0,1,0]
3697 // take_cyclic(2, [0,1,2,3]) == [0,1]
3698 // take_cyclic(3, [0]) == [0,0,0]
3699 // take_cyclic(3, []) == crash!
3700 // Also known as take_wrap.
3701 // xs must be non-empty.
3702 template <typename Container>
take_cyclic(std::size_t amount,const Container & xs)3703 Container take_cyclic(std::size_t amount, const Container& xs)
3704 {
3705     assert(!xs.empty());
3706 
3707     Container ys;
3708     internal::prepare_container(ys, size_of_cont(xs));
3709     auto it_out = internal::get_back_inserter(ys);
3710     auto it_in = std::begin(xs);
3711 
3712     while (amount != 0)
3713     {
3714         *it_out = *it_in;
3715         --amount;
3716         ++it_in;
3717         if (it_in == std::end(xs))
3718         {
3719             it_in = std::begin(xs);
3720         }
3721     }
3722     return ys;
3723 }
3724 
3725 // API search type: drop : (Int, [a]) -> [a]
3726 // fwd bind count: 1
3727 // Skip the first n elements of a sequence xs.
3728 // If n > length(xs) an empty sequence is returned.
3729 // drop(3, [0,1,2,3,4,5,6,7]) == [3,4,5,6,7]
3730 // Also known as skip.
3731 template <typename Container,
3732     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
drop(std::size_t amount,Container && xs)3733 ContainerOut drop(std::size_t amount, Container&& xs)
3734 {
3735     if (amount >= size_of_cont(xs))
3736         return ContainerOut();
3737     return get_segment(amount, size_of_cont(xs), std::forward<Container>(xs));
3738 }
3739 
3740 // API search type: take_last : (Int, [a]) -> [a]
3741 // fwd bind count: 1
3742 // Return the last n elements of a sequence xs.
3743 // In case n >= length(xs), xs is returned.
3744 // take_last(3, [0,1,2,3,4,5,6,7]) == [5,6,7]
3745 // take_last(10, [0,1,2]) == [0,1,2]
3746 template <typename Container,
3747     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
take_last(std::size_t amount,Container && xs)3748 ContainerOut take_last(std::size_t amount, Container&& xs)
3749 {
3750     if (amount >= size_of_cont(xs))
3751         return xs;
3752     return drop(size_of_cont(xs) - amount, std::forward<Container>(xs));
3753 }
3754 
3755 // API search type: drop_last : (Int, [a]) -> [a]
3756 // fwd bind count: 1
3757 // Skip the last n elements of a sequence xs.
3758 // If n > length(xs) an empty sequence is returned.
3759 // drop_last(3, [0,1,2,3,4,5,6,7]) == [0,1,2,3,4]
3760 template <typename Container,
3761     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
drop_last(std::size_t amount,Container && xs)3762 ContainerOut drop_last(std::size_t amount, Container&& xs)
3763 {
3764     if (amount >= size_of_cont(xs))
3765         return ContainerOut();
3766     return take(size_of_cont(xs) - amount, std::forward<Container>(xs));
3767 }
3768 
3769 // API search type: drop_exact : (Int, [a]) -> [a]
3770 // fwd bind count: 1
3771 // Skip exactly the first n elements of a sequence xs.
3772 // Unsafe! Crashes when xs is too short.
3773 // drop_exact(3, [0,1,2,3,4,5,6,7]) == [3,4,5,6,7]
3774 // drop_exact(10, [0,1,2,3,4,5,6,7]) == crash
3775 template <typename Container,
3776     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
drop_exact(std::size_t amount,Container && xs)3777 ContainerOut drop_exact(std::size_t amount, Container&& xs)
3778 {
3779     return get_segment(amount, size_of_cont(xs), std::forward<Container>(xs));
3780 }
3781 
3782 // API search type: take_while : ((a -> Bool), [a]) -> [a]
3783 // fwd bind count: 1
3784 // Take elements from the beginning of a sequence
3785 // as long as they are fulfilling a predicate.
3786 // take_while(is_even, [0,2,4,5,6,7,8]) == [0,2,4]
3787 template <typename Container, typename UnaryPredicate>
3788 Container take_while(UnaryPredicate pred, const Container& xs)
3789 {
3790     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
3791     auto itFirst = std::find_if(
3792         std::begin(xs), std::end(xs), logical_not(pred));
3793     if (itFirst == std::end(xs))
3794         return xs;
3795     return Container(std::begin(xs), itFirst);
3796 }
3797 
3798 // API search type: take_last_while : ((a -> Bool), [a]) -> [a]
3799 // fwd bind count: 1
3800 // Take elements from the beginning of a sequence
3801 // as long as they are fulfilling a predicate.
3802 // take_last_while(is_even, [0,2,7,5,6,4,8]) == [6,4,8]
3803 template <typename Container, typename UnaryPredicate>
3804 Container take_last_while(UnaryPredicate pred, const Container& xs)
3805 {
3806     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
3807     const auto r_begin = internal::make_reverse_iterator(std::end(xs));
3808     const auto r_end = internal::make_reverse_iterator(std::begin(xs));
3809     const auto itFirstReverse = std::find_if(r_begin, r_end, logical_not(pred));
3810     if (itFirstReverse == r_begin)
3811         return Container();
3812     if (itFirstReverse == r_end)
3813         return xs;
3814     return Container(itFirstReverse.base(), std::end(xs));
3815 }
3816 
3817 // API search type: drop_while : ((a -> Bool), [a]) -> [a]
3818 // fwd bind count: 1
3819 // Remove elements from the beginning of a sequence
3820 // as long as they are fulfilling a predicate.
3821 // drop_while(is_even, [0,2,4,5,6,7,8]) == [5,6,7,8]
3822 // Also known as trim_left_by.
3823 template <typename Container, typename UnaryPredicate>
3824 Container drop_while(UnaryPredicate pred, const Container& xs)
3825 {
3826     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
3827     auto itFirstNot = std::find_if_not(std::begin(xs), std::end(xs), pred);
3828     if (itFirstNot == std::end(xs))
3829         return Container();
3830     return Container(itFirstNot, std::end(xs));
3831 }
3832 
3833 // API search type: drop_last_while : ((a -> Bool), [a]) -> [a]
3834 // fwd bind count: 1
3835 // Remove elements from the beginning of a sequence
3836 // as long as they are fulfilling a predicate.
3837 // drop_last_while(is_even, [0,2,7,5,6,4,8]) == [0,2,7,5]
3838 template <typename Container, typename UnaryPredicate>
3839 Container drop_last_while(UnaryPredicate pred, const Container& xs)
3840 {
3841     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
3842     const auto r_begin = internal::make_reverse_iterator(std::end(xs));
3843     const auto r_end = internal::make_reverse_iterator(std::begin(xs));
3844     const auto itFirstNotReverse = std::find_if_not(r_begin, r_end, pred);
3845     if (itFirstNotReverse == r_begin)
3846         return xs;
3847     if (itFirstNotReverse == r_end)
3848         return Container();
3849     return Container(std::begin(xs), itFirstNotReverse.base());
3850 }
3851 
3852 // API search type: fold_left : (((a, b) -> a), a, [b]) -> a
3853 // fwd bind count: 2
3854 // fold_left((+), 0, [1, 2, 3]) == ((0+1)+2)+3 == 6
3855 // Takes the second argument and the first item of the list
3856 // and applies the function to them,
3857 // then feeds the function with this result and the second argument and so on.
3858 template <typename F, typename Container, typename Acc>
fold_left(F f,const Acc & init,const Container & xs)3859 Acc fold_left(F f, const Acc& init, const Container& xs)
3860 {
3861     using std::begin;
3862     using std::end;
3863 
3864     return internal::accumulate(begin(xs), end(xs), init, f);
3865 }
3866 
3867 // API search type: reduce : (((a, a) -> a), a, [a]) -> a
3868 // fwd bind count: 2
3869 // reduce((+), 0, [1, 2, 3]) == (0+1+2+3) == 6
3870 // Combines the initial value and all elements of the sequence
3871 // using the given function.
3872 // The set of f, init and value_type should form a monoid.
3873 template <typename F, typename Container>
reduce(F f,const typename Container::value_type & init,const Container & xs)3874 typename Container::value_type reduce(
3875     F f, const typename Container::value_type& init, const Container& xs)
3876 {
3877     return fold_left(f, init, xs);
3878 }
3879 
3880 // API search type: fold_left_1 : (((a, a) -> a), [a]) -> a
3881 // fwd bind count: 1
3882 // fold_left_1((+), [1, 2, 3]) == (1+2)+3 == 6
3883 // Takes the first 2 items of the list and applies the function to them,
3884 // then feeds the function with this result and the third argument and so on.
3885 // xs must be non-empty.
3886 template <typename F, typename Container>
fold_left_1(F f,const Container & xs)3887 auto fold_left_1(F f, const Container& xs)
3888 {
3889     assert(!xs.empty());
3890 
3891     using std::begin;
3892     using std::end;
3893 
3894     const auto it = begin(xs);
3895     return internal::accumulate(std::next(it), end(xs), *it, f);
3896 }
3897 
3898 // API search type: reduce_1 : (((a, a) -> a), [a]) -> a
3899 // fwd bind count: 1
3900 // reduce_1((+), [1, 2, 3]) == (1+2+3) == 6
3901 // Joins all elements of the sequence using the given function.
3902 // The set of f and value_type should form a semigroup.
3903 template <typename F, typename Container>
reduce_1(F f,const Container & xs)3904 typename Container::value_type reduce_1(F f, const Container& xs)
3905 {
3906     assert(!xs.empty());
3907     return fold_left_1(f, xs);
3908 }
3909 
3910 // API search type: fold_right : (((a, b) -> b), b) -> [a] -> b
3911 // fwd bind count: 2
3912 // fold_right((+), 0, [1, 2, 3]) == 1+(2+(3+0)) == 6
3913 // Takes the second argument and the last item of the list
3914 // and applies the function,
3915 // then it takes the penultimate item from the end and the result, and so on.
3916 template <typename F, typename Container, typename Acc>
fold_right(F f,const Acc & init,const Container & xs)3917 Acc fold_right(F f, const Acc& init, const Container& xs)
3918 {
3919     return internal::accumulate(xs.rbegin(), xs.rend(), init, flip(f));
3920 }
3921 
3922 // API search type: fold_right_1 : (((a, a) -> a), [a]) -> a
3923 // fwd bind count: 1
3924 // fold_right_1((+), [1, 2, 3]) == 1+(2+3)) == 6
3925 // Takes the last two items of the list and applies the function,
3926 // then it takes the third item from the end and the result, and so on.
3927 template <typename F, typename Container>
fold_right_1(F f,const Container & xs)3928 auto fold_right_1(F f, const Container& xs)
3929 {
3930     assert(!xs.empty());
3931     const auto it = xs.rbegin();
3932     return internal::accumulate(std::next(it), xs.rend(), *it, flip(f));
3933 }
3934 
3935 // API search type: scan_left : (((a, b) -> a), a, [b]) -> [a]
3936 // fwd bind count: 2
3937 // scan_left((+), 0, [1, 2, 3]) == [0, 1, 3, 6]
3938 // Takes the second argument and the first item of the list
3939 // and applies the function to them,
3940 // then feeds the function with this result and the second argument and so on.
3941 // It returns the list of intermediate and final results.
3942 template <typename F, typename ContainerIn, typename Acc>
scan_left(F f,const Acc & init,const ContainerIn & xs)3943 auto scan_left(F f, const Acc& init, const ContainerIn& xs)
3944 {
3945     using ContainerOut =
3946         typename internal::same_cont_new_t<ContainerIn, Acc, 1>::type;
3947 
3948     ContainerOut result;
3949     internal::prepare_container(result, size_of_cont(xs) + 1);
3950 
3951     using std::begin;
3952     using std::end;
3953 
3954     internal::scan_impl(
3955         f, init, internal::get_back_inserter(result), begin(xs), end(xs));
3956     return result;
3957 }
3958 
3959 // API search type: scan_left_1 : (((a, a) -> a), [a]) -> [a]
3960 // fwd bind count: 1
3961 // scan_left_1((+), [1, 2, 3]) == [1, 3, 6]
3962 // Takes the first 2 items of the list and applies the function to them,
3963 // then feeds the function with this result and the third argument and so on.
3964 // It returns the list of intermediate and final results.
3965 // xs must be non-empty.
3966 template <typename F, typename ContainerIn>
scan_left_1(F f,const ContainerIn & xs)3967 auto scan_left_1(F f, const ContainerIn& xs)
3968 {
3969     assert(!xs.empty());
3970 
3971     using std::begin;
3972     using std::end;
3973 
3974     const auto beginIt = begin(xs);
3975 
3976     using ContainerOut = typename internal::same_cont_new_t<
3977         ContainerIn,
3978         internal::uncvref_t<decltype(*beginIt)>,
3979         0>::type;
3980 
3981     ContainerOut result;
3982     internal::prepare_container(result, size_of_cont(xs));
3983     internal::scan_impl(f,
3984                       *beginIt,
3985                       internal::get_back_inserter(result),
3986                       std::next(beginIt),
3987                       end(xs));
3988     return result;
3989 }
3990 
3991 // API search type: scan_right : (((a, b) -> b), b, [a]) -> [b]
3992 // fwd bind count: 2
3993 // scan_right((+), 0, [1, 2, 3]) == [6, 5, 3, 0]
3994 // Takes the second argument and the last item of the list
3995 // and applies the function,
3996 // then it takes the penultimate item from the end and the result, and so on.
3997 // It returns the list of intermediate and final results.
3998 template <typename F, typename ContainerIn,
3999     typename Acc = typename utils::function_traits<F>::template arg<1>::type,
4000     typename ContainerOut = typename internal::same_cont_new_t<ContainerIn, Acc, 1>::type>
scan_right(F f,const Acc & init,const ContainerIn & xs)4001 ContainerOut scan_right(F f, const Acc& init, const ContainerIn& xs)
4002 {
4003     return reverse(scan_left(flip(f), init, reverse(xs)));
4004 }
4005 
4006 // API search type: scan_right_1 : (((a, a) -> a), [a]) -> [a]
4007 // fwd bind count: 1
4008 // scan_right_1((+), [1, 2, 3]) == [6, 5, 3]
4009 // Takes the last two items of the list and applies the function,
4010 // then it takes the third item from the end and the result, and so on.
4011 // It returns the list of inntermediate and final results.
4012 template <typename F, typename ContainerIn,
4013     typename Acc = typename ContainerIn::value_type,
4014     typename ContainerOut = typename internal::same_cont_new_t<ContainerIn, Acc, 0>::type>
scan_right_1(F f,const ContainerIn & xs)4015 ContainerOut scan_right_1(F f, const ContainerIn& xs)
4016 {
4017     return reverse(scan_left_1(flip(f), reverse(xs)));
4018 }
4019 
4020 // API search type: sum : [a] -> a
4021 // fwd bind count: 0
4022 // Adds up all values in a sequence.
4023 // sum([0,3,1]) == 4
4024 // sum([]) == 0
4025 template <typename Container,
4026     typename T = typename Container::value_type>
sum(const Container & xs)4027 T sum(const Container& xs)
4028 {
4029     T result = T();
4030     for (const auto& x : xs)
4031     {
4032         result = result + x;
4033     }
4034     return result;
4035 }
4036 
4037 // API search type: product : [a] -> a
4038 // fwd bind count: 0
4039 // Returns the product of all values in a sequence.
4040 // product([3,1,2]) == 6
4041 // product([]) == 1
4042 template <typename Container,
4043     typename T = typename Container::value_type>
product(const Container & xs)4044 T product(const Container& xs)
4045 {
4046     T result{1};
4047     for (const auto& x : xs)
4048     {
4049         result = result * x;
4050     }
4051     return result;
4052 }
4053 
4054 namespace internal
4055 {
4056 
4057 template <typename T, typename Container>
append_elem(internal::reuse_container_t,const T & y,Container && xs)4058 Container append_elem(internal::reuse_container_t, const T& y, Container&& xs)
4059 {
4060     *internal::get_back_inserter(xs) = y;
4061     return std::forward<Container>(xs);
4062 }
4063 
4064 template <typename T, typename Container>
append_elem(internal::create_new_container_t,const T & y,const Container & xs)4065 Container append_elem(internal::create_new_container_t, const T& y,
4066     const Container& xs)
4067 {
4068     Container result;
4069     internal::prepare_container(result, size_of_cont(xs) + 1);
4070     std::copy(std::begin(xs), std::end(xs),
4071         internal::get_back_inserter(result));
4072     *internal::get_back_inserter(result) = y;
4073     return result;
4074 }
4075 
4076 } // namespace internal
4077 
4078 // API search type: append_elem : (a, [a]) -> [a]
4079 // fwd bind count: 1
4080 // Extends a sequence with one element at the back.
4081 // append_elem([1, 2], 3) == [1, 2, 3]
4082 template <typename Container,
4083     typename ContainerOut = internal::remove_const_and_ref_t<Container>,
4084     typename T = typename ContainerOut::value_type>
4085 ContainerOut append_elem(const T& y, Container&& xs)
4086 {
4087     return internal::append_elem(internal::can_reuse_v<Container>{},
4088         y, std::forward<Container>(xs));
4089 }
4090 
4091 namespace internal
4092 {
4093 
4094 template <typename T>
prepend_elem(internal::reuse_container_t,const T & y,std::list<T> && xs)4095 std::list<T> prepend_elem(internal::reuse_container_t,
4096     const T& y, std::list<T>&& xs)
4097 {
4098     xs.push_front(y);
4099     return std::forward<std::list<T>>(xs);
4100 }
4101 
4102 template <typename T, typename Container>
prepend_elem(internal::reuse_container_t,const T & y,Container && xs)4103 Container prepend_elem(internal::reuse_container_t,
4104     const T& y, Container&& xs)
4105 {
4106     xs.resize(size_of_cont(xs) + 1);
4107     std::copy(++xs.rbegin(), xs.rend(), xs.rbegin());
4108     *std::begin(xs) = y;
4109     return std::forward<Container>(xs);
4110 }
4111 
4112 template <typename T, typename Container>
prepend_elem(internal::create_new_container_t,const T & y,const Container & xs)4113 Container prepend_elem(internal::create_new_container_t, const T& y,
4114     const Container& xs)
4115 {
4116     Container result;
4117     internal::prepare_container(result, size_of_cont(xs) + 1);
4118     *internal::get_back_inserter(result) = y;
4119     std::copy(std::begin(xs), std::end(xs),
4120         internal::get_back_inserter(result));
4121     return result;
4122 }
4123 
4124 } // namespace internal
4125 
4126 // API search type: prepend_elem : (a, [a]) -> [a]
4127 // fwd bind count: 1
4128 // Extends a sequence with one element in the front.
4129 // prepend_elem([2, 3], 1) == [1, 2, 3]
4130 template <typename Container,
4131     typename ContainerOut = internal::remove_const_and_ref_t<Container>,
4132     typename T = typename ContainerOut::value_type>
4133 ContainerOut prepend_elem(const T& y, Container&& xs)
4134 {
4135     return internal::prepend_elem(internal::can_reuse_v<Container>{},
4136         y, std::forward<Container>(xs));
4137 }
4138 
4139 // API search type: append : ([a], [a]) -> [a]
4140 // fwd bind count: 1
4141 // Concatenates two sequences.
4142 // append([1, 2], [3, 4, 5]) == [1, 2, 3, 4, 5]
4143 template <typename ContainerIn1, typename ContainerIn2 = ContainerIn1, typename ContainerOut = ContainerIn1>
append(const ContainerIn1 & xs,const ContainerIn2 & ys)4144 ContainerOut append(const ContainerIn1& xs, const ContainerIn2& ys)
4145 {
4146     ContainerOut result;
4147     internal::prepare_container(result, size_of_cont(xs) + size_of_cont(ys));
4148     std::copy(std::begin(xs), std::end(xs),
4149         internal::get_back_inserter(result));
4150     std::copy(std::begin(ys), std::end(ys),
4151         internal::get_back_inserter(result));
4152     return result;
4153 }
4154 
4155 
4156 // API search type: append_convert : ([a], [a]) -> [a]
4157 // fwd bind count: 1
4158 // Same as append, but makes it easier to
4159 // use an output container type different from the input container type.
4160 template <typename ContainerOut, typename ContainerIn1, typename ContainerIn2 = ContainerIn1>
4161 ContainerOut append_convert(const ContainerIn1& xs, const ContainerIn2& ys)
4162 {
4163     return append<ContainerIn1, ContainerIn2, ContainerOut>(xs, ys);
4164 }
4165 
4166 // API search type: concat : [[a]] -> [a]
4167 // fwd bind count: 0
4168 // Concatenates multiple sequences.
4169 // concat([[1, 2], [], [3]]) == [1, 2, 3]
4170 // Also known as flatten.
4171 template <typename ContainerIn,
4172     typename ContainerOut = typename ContainerIn::value_type>
concat(const ContainerIn & xss)4173 ContainerOut concat(const ContainerIn& xss)
4174 {
4175     std::size_t length = sum(
4176         transform(size_of_cont<typename ContainerIn::value_type>, xss));
4177     ContainerOut result;
4178     internal::prepare_container(result, length);
4179     using std::begin;
4180     using std::end;
4181     for(const auto& xs : xss)
4182     {
4183         result.insert(end(result), begin(xs), end(xs));
4184     }
4185     return result;
4186 }
4187 
4188 // API search type: interweave : ([a], [a]) -> [a]
4189 // fwd bind count: 1
4190 // Return a sequence that contains elements from the two provided sequences
4191 // in alternating order. If one list runs out of items,
4192 // appends the items from the remaining list.
4193 // interweave([1,3], [2,4]) == [1,2,3,4]
4194 // interweave([1,3,5,7], [2,4]) == [1,2,3,4,5,7]
4195 // See interleave for interweaving more than two sequences.
4196 template <typename Container>
interweave(const Container & xs,const Container & ys)4197 Container interweave(const Container& xs, const Container& ys)
4198 {
4199     Container result;
4200     internal::prepare_container(result, size_of_cont(xs) + size_of_cont(ys));
4201     auto it = internal::get_back_inserter<Container>(result);
4202     auto it_xs = std::begin(xs);
4203     auto it_ys = std::begin(ys);
4204     while (it_xs != std::end(xs) || it_ys != std::end(ys))
4205     {
4206         if (it_xs != std::end(xs))
4207             *it = *(it_xs++);
4208         if (it_ys != std::end(ys))
4209             *it = *(it_ys++);
4210     }
4211     return result;
4212 }
4213 
4214 // API search type: unweave : [a] -> ([a], [a])
4215 // fwd bind count: 0
4216 // Puts the elements with an even index into the first list,
4217 // and the elements with an odd index into the second list.
4218 // Inverse of interweave.
4219 // unweave([0,1,2,3]) == ([0,2], [1,3])
4220 // unweave([0,1,2,3,4]) == ([0,2,4], [1,3])
4221 template <typename Container>
unweave(const Container & xs)4222 std::pair<Container, Container> unweave(const Container& xs)
4223 {
4224     std::pair<Container, Container> result;
4225     if (is_even(size_of_cont(xs)))
4226         internal::prepare_container(result.first, size_of_cont(xs) / 2);
4227     else
4228         internal::prepare_container(result.first, size_of_cont(xs) / 2 + 1);
4229     internal::prepare_container(result.second, size_of_cont(xs) / 2);
4230     auto it_even = internal::get_back_inserter<Container>(result.first);
4231     auto it_odd = internal::get_back_inserter<Container>(result.second);
4232     std::size_t counter = 0;
4233     for (const auto& x : xs)
4234     {
4235         if (counter++ % 2 == 0)
4236             *it_even = x;
4237         else
4238             *it_odd = x;
4239     }
4240     return result;
4241 }
4242 
4243 namespace internal
4244 {
4245 
4246 template <typename Compare, typename T>
sort_by(internal::reuse_container_t,Compare comp,std::list<T> && xs)4247 std::list<T> sort_by(internal::reuse_container_t, Compare comp,
4248     std::list<T>&& xs)
4249 {
4250     xs.sort(comp);
4251     return std::forward<std::list<T>>(xs);
4252 }
4253 
4254 template <typename Compare, typename T>
sort_by(internal::create_new_container_t,Compare comp,const std::list<T> & xs)4255 std::list<T> sort_by(internal::create_new_container_t, Compare comp,
4256     const std::list<T>& xs)
4257 {
4258     auto result = xs;
4259     result.sort(comp);
4260     return result;
4261 }
4262 
4263 template <typename Compare, typename Container>
sort_by(internal::reuse_container_t,Compare comp,Container && xs)4264 Container sort_by(internal::reuse_container_t, Compare comp, Container&& xs)
4265 {
4266     std::sort(std::begin(xs), std::end(xs), comp);
4267     return std::forward<Container>(xs);
4268 }
4269 
4270 template <typename Compare, typename Container>
sort_by(internal::create_new_container_t,Compare comp,const Container & xs)4271 Container sort_by(internal::create_new_container_t, Compare comp,
4272     const Container& xs)
4273 {
4274     auto result = xs;
4275     std::sort(std::begin(result), std::end(result), comp);
4276     return result;
4277 }
4278 
4279 } // namespace internal
4280 
4281 // API search type: sort_by : (((a, a) -> Bool), [a]) -> [a]
4282 // fwd bind count: 1
4283 // Sort a sequence by given less comparator.
4284 template <typename Compare, typename Container,
4285     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
sort_by(Compare comp,Container && xs)4286 ContainerOut sort_by(Compare comp, Container&& xs)
4287 {
4288     return internal::sort_by(internal::can_reuse_v<Container>{},
4289         comp, std::forward<Container>(xs));
4290 }
4291 
4292 namespace internal
4293 {
4294     // workarounds for clang bug 24115
4295     // (std::sort and std::unique with std::function as comp)
4296     // https://llvm.org/bugs/show_bug.cgi?id=24115
4297     template <typename F>
4298     struct is_less_by_struct
4299     {
is_less_by_structfplus::internal::is_less_by_struct4300         is_less_by_struct(F f) : f_(f) {};
4301         template <typename T>
operator ()fplus::internal::is_less_by_struct4302         bool operator()(const T& x, const T& y)
4303         {
4304             return f_(x) < f_(y);
4305         }
4306     private:
4307         F f_;
4308     };
4309     template <typename F>
4310     struct is_equal_by_struct
4311     {
is_equal_by_structfplus::internal::is_equal_by_struct4312         is_equal_by_struct(F f) : f_(f) {};
4313         template <typename T>
operator ()fplus::internal::is_equal_by_struct4314         bool operator()(const T& x, const T& y)
4315         {
4316             return f_(x) == f_(y);
4317         }
4318     private:
4319         F f_;
4320     };
4321 }
4322 
4323 // API search type: sort_on : ((a -> b), [a]) -> [a]
4324 // fwd bind count: 1
4325 // Sort a sequence by a given transformer.
4326 template <typename F, typename Container,
4327     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
sort_on(F f,Container && xs)4328 ContainerOut sort_on(F f, Container&& xs)
4329 {
4330     return sort_by(internal::is_less_by_struct<F>(f),
4331         std::forward<Container>(xs));
4332 }
4333 
4334 // API search type: sort : [a] -> [a]
4335 // fwd bind count: 0
4336 // Sort a sequence to ascending order using std::less.
4337 template <typename Container,
4338     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
sort(Container && xs)4339 ContainerOut sort(Container&& xs)
4340 {
4341     typedef typename std::remove_reference<Container>::type::value_type T;
4342     return sort_by(std::less<T>(), std::forward<Container>(xs));
4343 }
4344 
4345 namespace internal
4346 {
4347 
4348 template <typename Compare, typename T>
stable_sort_by(internal::reuse_container_t,Compare comp,std::list<T> && xs)4349 std::list<T> stable_sort_by(internal::reuse_container_t, Compare comp,
4350     std::list<T>&& xs)
4351 {
4352     xs.sort(comp); // std::list<T>::sort ist already stable.
4353     return std::forward<std::list<T>>(xs);
4354 }
4355 
4356 template <typename Compare, typename T>
stable_sort_by(internal::create_new_container_t,Compare comp,const std::list<T> & xs)4357 std::list<T> stable_sort_by(internal::create_new_container_t, Compare comp,
4358     const std::list<T>& xs)
4359 {
4360     auto result = xs;
4361     result.sort(comp); // std::list<T>::sort ist already stable.
4362     return result;
4363 }
4364 
4365 template <typename Compare, typename Container>
stable_sort_by(internal::reuse_container_t,Compare comp,Container && xs)4366 Container stable_sort_by(internal::reuse_container_t, Compare comp,
4367     Container&& xs)
4368 {
4369     std::sort(std::begin(xs), std::end(xs), comp);
4370     return std::forward<Container>(xs);
4371 }
4372 
4373 template <typename Compare, typename Container>
stable_sort_by(internal::create_new_container_t,Compare comp,const Container & xs)4374 Container stable_sort_by(internal::create_new_container_t, Compare comp,
4375     const Container& xs)
4376 {
4377     auto result = xs;
4378     std::sort(std::begin(result), std::end(result), comp);
4379     return result;
4380 }
4381 
4382 } // namespace internal
4383 
4384 
4385 // API search type: stable_sort_by : (((a, a) -> Bool), [a]) -> [a]
4386 // fwd bind count: 1
4387 // Sort a sequence stably by given less comparator.
4388 template <typename Compare, typename Container,
4389     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
stable_sort_by(Compare comp,Container && xs)4390 ContainerOut stable_sort_by(Compare comp, Container&& xs)
4391 {
4392     return internal::stable_sort_by(internal::can_reuse_v<Container>{},
4393         comp, std::forward<Container>(xs));
4394 }
4395 
4396 // API search type: stable_sort_on : ((a -> b), [a]) -> [a]
4397 // fwd bind count: 1
4398 // Sort a sequence stably by given transformer.
4399 template <typename F, typename Container,
4400     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
stable_sort_on(F f,Container && xs)4401 ContainerOut stable_sort_on(F f, Container&& xs)
4402 {
4403     return stable_sort_by(internal::is_less_by_struct<F>(f),
4404         std::forward<Container>(xs));
4405 }
4406 
4407 // API search type: stable_sort : [a] -> [a]
4408 // fwd bind count: 0
4409 // Sort a sequence stably to ascending order using std::less.
4410 template <typename Container,
4411     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
stable_sort(Container && xs)4412 ContainerOut stable_sort(Container&& xs)
4413 {
4414     typedef typename std::remove_reference<Container>::type::value_type T;
4415     return stable_sort_by(std::less<T>(), std::forward<Container>(xs));
4416 }
4417 
4418 namespace internal
4419 {
4420 
4421 template <typename Compare, typename Container>
partial_sort_by(internal::reuse_container_t,Compare comp,std::size_t count,Container && xs)4422 Container partial_sort_by(internal::reuse_container_t, Compare comp,
4423     std::size_t count, Container&& xs)
4424 {
4425     if (count > xs.size())
4426     {
4427         count = xs.size();
4428     }
4429     auto middle = std::begin(xs);
4430     internal::advance_iterator(middle, count);
4431     std::partial_sort(std::begin(xs), middle, std::end(xs), comp);
4432     return std::forward<Container>(get_segment(internal::reuse_container_t(),
4433         0, count, xs));
4434 }
4435 
4436 template <typename Compare, typename Container>
partial_sort_by(internal::create_new_container_t,Compare comp,std::size_t count,const Container & xs)4437 Container partial_sort_by(internal::create_new_container_t, Compare comp,
4438     std::size_t count, const Container& xs)
4439 {
4440     auto result = xs;
4441     return partial_sort_by(
4442         internal::reuse_container_t(), comp, count, std::move(result));
4443 }
4444 
4445 } // namespace internal
4446 
4447 // API search type: partial_sort_by : (((a, a) -> Bool), Int, [a]) -> [a]
4448 // fwd bind count: 2
4449 // Partially sort a sequence by a given less comparator.
4450 // Returns only the sorted segment.
4451 template <typename Compare, typename Container,
4452     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
partial_sort_by(Compare comp,std::size_t count,Container && xs)4453 ContainerOut partial_sort_by(Compare comp, std::size_t count, Container&& xs)
4454 {
4455     return internal::partial_sort_by(internal::can_reuse_v<Container>{},
4456         comp, count, std::forward<Container>(xs));
4457 }
4458 
4459 // API search type: partial_sort_on : ((a -> b), Int, [a]) -> [a]
4460 // fwd bind count: 2
4461 // Partially sort a sequence by a given transformer.
4462 // Returns only the sorted segment.
4463 template <typename F, typename Container,
4464     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
partial_sort_on(F f,std::size_t count,Container && xs)4465 ContainerOut partial_sort_on(F f, std::size_t count, Container&& xs)
4466 {
4467     return partial_sort_by(internal::is_less_by_struct<F>(f), count,
4468         std::forward<Container>(xs));
4469 }
4470 
4471 // API search type: partial_sort : (Int, [a]) -> [a]
4472 // fwd bind count: 1
4473 // Partially sort a sequence in ascending order using std::less.
4474 // Returns only the sorted segment.
4475 template <typename Container,
4476     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
partial_sort(std::size_t count,Container && xs)4477 ContainerOut partial_sort(std::size_t count, Container&& xs)
4478 {
4479     typedef typename std::remove_reference<Container>::type::value_type T;
4480     return partial_sort_by(std::less<T>(), count,
4481         std::forward<Container>(xs));
4482 }
4483 
4484 // API search type: nth_element_by : (((a, a) -> Bool), Int, [a]) -> a
4485 // fwd bind count: 2
4486 // Return the nth largest element of a sequence by a given less comparator.
4487 template <typename Compare, typename Container,
4488     typename T = typename Container::value_type>
nth_element_by(Compare comp,std::size_t n,const Container & xs)4489 T nth_element_by(Compare comp, std::size_t n, const Container& xs)
4490 {
4491     assert(n < xs.size());
4492     auto result = xs;
4493     auto middle = std::begin(result);
4494     internal::advance_iterator(middle, n);
4495     std::nth_element(std::begin(result), middle, std::end(result), comp);
4496     return *middle;
4497 }
4498 
4499 // API search type: nth_element_on : ((a -> b), Int, [a]) -> a
4500 // fwd bind count: 2
4501 // Return the nth largest element of a sequence by a given transformer.
4502 template <typename F, typename Container,
4503     typename T = typename Container::value_type>
nth_element_on(F f,std::size_t n,const Container & xs)4504 T nth_element_on(F f, std::size_t n, const Container& xs)
4505 {
4506     return nth_element_by(internal::is_less_by_struct<F>(f), n, xs);
4507 }
4508 
4509 // API search type: nth_element : (Int, [a]) -> a
4510 // fwd bind count: 1
4511 // Return the nth largest element of a sequence using std::less.
4512 template <typename Container,
4513     typename T = typename Container::value_type>
nth_element(std::size_t n,const Container & xs)4514 T nth_element(std::size_t n, const Container& xs)
4515 {
4516     return nth_element_by(std::less<T>(), n, xs);
4517 }
4518 
4519 namespace internal
4520 {
4521 
4522 template <typename BinaryPredicate, typename Container>
unique_by(internal::reuse_container_t,BinaryPredicate pred,Container && xs)4523 Container unique_by(internal::reuse_container_t,
4524     BinaryPredicate pred, Container&& xs)
4525 {
4526     internal::check_binary_predicate_for_container<BinaryPredicate, Container>();
4527     const auto it_end = std::unique(std::begin(xs), std::end(xs), pred);
4528     xs.erase(it_end, std::end(xs));
4529     return std::forward<Container>(xs);
4530 }
4531 
4532 template <typename BinaryPredicate, typename Container>
unique_by(internal::create_new_container_t,BinaryPredicate pred,const Container & xs)4533 Container unique_by(internal::create_new_container_t,
4534     BinaryPredicate pred, const Container& xs)
4535 {
4536     auto result = xs;
4537     return unique_by(internal::reuse_container_t(), pred, std::move(result));
4538 }
4539 
4540 } // namespace internal
4541 
4542 // API search type: unique_by : (((a, a) -> Bool), [a]) -> [a]
4543 // fwd bind count: 1
4544 // Like unique, eliminates all but the first element
4545 // from every consecutive group of equivalent elements from the sequence;
4546 // but with a user supplied equality predicate.
4547 // See nub_by for making elements globally unique in a sequence.
4548 // O(n)
4549 template <typename BinaryPredicate, typename Container,
4550     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
unique_by(BinaryPredicate pred,Container && xs)4551 ContainerOut unique_by(BinaryPredicate pred, Container&& xs)
4552 {
4553     return internal::unique_by(internal::can_reuse_v<Container>{},
4554         pred, std::forward<Container>(xs));
4555 }
4556 
4557 // API search type: unique_on : ((a -> b), [a]) -> [a]
4558 // fwd bind count: 1
4559 // Like unique, eliminates all but the first element
4560 // from every consecutive group of equivalent elements from the sequence;
4561 // but with a user supplied transformation (e.g. getter).
4562 // See nub_on for making elements globally unique in a sequence.
4563 // O(n)
4564 // Also known as drop_repeats.
4565 template <typename F, typename Container,
4566     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
unique_on(F f,Container && xs)4567 ContainerOut unique_on(F f, Container&& xs)
4568 {
4569     return unique_by(internal::is_equal_by_struct<F>(f),
4570         std::forward<Container>(xs));
4571 }
4572 
4573 // API search type: unique : [a] -> [a]
4574 // fwd bind count: 0
4575 // Eliminates all but the first element
4576 // from every consecutive group of equivalent elements from the sequence.
4577 // unique([1,2,2,3,2]) == [1,2,3,2]
4578 // See nub for making elements globally unique in a sequence.
4579 // O(n)
4580 template <typename Container,
4581     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
unique(Container && xs)4582 ContainerOut unique(Container&& xs)
4583 {
4584     typedef typename std::remove_reference<Container>::type::value_type T;
4585     return unique_on(identity<T>, std::forward<Container>(xs));
4586 }
4587 
4588 // API search type: intersperse : (a, [a]) -> [a]
4589 // fwd bind count: 1
4590 // Insert a value between all adjacent values in a sequence.
4591 // intersperse(0, [1, 2, 3]) == [1, 0, 2, 0, 3]
4592 // Also known as interpose.
4593 template <typename Container,
4594     typename X = typename Container::value_type>
4595 Container intersperse(const X& value, const Container& xs)
4596 {
4597     if (xs.empty())
4598         return Container();
4599     if (size_of_cont(xs) == 1)
4600         return xs;
4601     Container result;
4602     internal::prepare_container(result, std::max<std::size_t>(0, size_of_cont(xs)*2-1));
4603     auto it = internal::get_back_inserter(result);
4604     for_each(std::begin(xs), --std::end(xs), [&value, &it](const X& x)
__anon1e7ca4c42702(const X& x) 4605     {
4606         *it = x;
4607         *it = value;
4608     });
4609     *it = xs.back();
4610     return result;
4611 }
4612 
4613 // API search type: join : ([a], [[a]]) -> [a]
4614 // fwd bind count: 1
4615 // Inserts a separator sequence in between the elements
4616 // of a sequence of sequences and concatenates the result.
4617 // Also known as intercalate or implode.
4618 // join(", ", ["a", "bee", "cee"]) == "a, bee, cee"
4619 // join([0, 0], [[1], [2], [3, 4]]) == [1, 0, 0, 2, 0, 0, 3, 4]
4620 template <typename Container,
4621     typename X = typename Container::value_type>
join(const X & separator,const Container & xs)4622 X join(const X& separator, const Container& xs)
4623 {
4624     return concat(intersperse(separator, xs));
4625 }
4626 
4627 // API search type: join_elem : (a, [[a]]) -> [a]
4628 // fwd bind count: 1
4629 // Inserts a separator in between the elements
4630 // of a sequence of sequences and concatenates the result.
4631 // Also known as intercalate_elem.
4632 // join_elem(';', ["a", "bee", "cee"]) == "a;bee;cee"
4633 // join_elem(0, [[1], [2], [3, 4]]) == [1, 0, 2, 0, 3, 4]]
4634 template <typename Container,
4635     typename Inner = typename Container::value_type,
4636     typename X = typename Inner::value_type>
4637 Inner join_elem(const X& separator, const Container& xs)
4638 {
4639     return join(Inner(1, separator), xs);
4640 }
4641 
4642 // API search type: is_elem_of_by : ((a -> Bool), [a]) -> Bool
4643 // fwd bind count: 1
4644 // Checks if at least one element of the container fulfils a predicate.
4645 // is_elem_of_by((==), [1,2,3]) == true
4646 template <typename UnaryPredicate, typename Container>
is_elem_of_by(UnaryPredicate pred,const Container & xs)4647 bool is_elem_of_by(UnaryPredicate pred, const Container& xs)
4648 {
4649     return std::find_if(std::begin(xs), std::end(xs), pred) != std::end(xs);
4650 }
4651 
4652 // API search type: is_elem_of : (a, [a]) -> Bool
4653 // fwd bind count: 1
4654 // Checks if an element is a member of a container.
4655 // is_elem_of(2, [1,2,3]) == true
4656 // Also known as flip(contains).
4657 template <typename Container>
is_elem_of(const typename Container::value_type & x,const Container & xs)4658 bool is_elem_of(const typename Container::value_type& x, const Container& xs)
4659 {
4660     return is_elem_of_by(is_equal_to(x), xs);
4661 }
4662 
4663 // API search type: nub_by : (((a, a) -> Bool), [a]) -> [a]
4664 // fwd bind count: 1
4665 // Makes the elements in a container unique with respect to a predicate
4666 // nub_by((==), [1,2,2,3,2]) == [1,2,3]
4667 // O(n^2)
4668 template <typename Container, typename BinaryPredicate>
4669 Container nub_by(BinaryPredicate p, const Container& xs)
4670 {
4671     Container result;
4672     auto itOut = internal::get_back_inserter(result);
4673     for (const auto &x : xs)
4674     {
4675         auto eqToX = bind_1st_of_2(p, x);
4676         if (!is_elem_of_by(eqToX, result))
4677         {
4678             *itOut = x;
4679         }
4680     }
4681     return result;
4682 }
4683 
4684 // API search type: nub_on : ((a -> b), [a]) -> [a]
4685 // fwd bind count: 1
4686 // Makes the elements in a container unique
4687 // with respect to their function value.
4688 // nub_on((mod 10), [12,32,15]) == [12,15]
4689 // O(n^2)
4690 template <typename Container, typename F>
4691 Container nub_on(F f, const Container& xs)
4692 {
4693     return nub_by(is_equal_by(f), xs);
4694 }
4695 
4696 // API search type: nub : [a] -> [a]
4697 // fwd bind count: 0
4698 // Makes the elements in a container unique.
4699 // nub([1,2,2,3,2]) == [1,2,3]
4700 // O(n^2)
4701 // Also known as distinct.
4702 template <typename Container>
nub(const Container & xs)4703 Container nub(const Container& xs)
4704 {
4705     typedef typename Container::value_type T;
4706     return nub_by(std::equal_to<T>(), xs);
4707 }
4708 
4709 // API search type: all_unique_by_eq : (((a, a) -> Bool), [a]) -> Bool
4710 // fwd bind count: 1
4711 // Checks if all elements in a container are unique
4712 // with respect to a predicate.
4713 // Returns true for empty containers.
4714 // O(n^2)
4715 template <typename Container, typename BinaryPredicate>
all_unique_by_eq(BinaryPredicate p,const Container & xs)4716 bool all_unique_by_eq(BinaryPredicate p, const Container& xs)
4717 {
4718     internal::check_binary_predicate_for_container<BinaryPredicate, Container>();
4719     return size_of_cont(nub_by(p, xs)) == size_of_cont(xs);
4720 }
4721 
4722 // API search type: all_unique_on : ((a -> b), [a]) -> Bool
4723 // fwd bind count: 1
4724 // Checks if all elements in a container are unique
4725 // with respect to their function values.
4726 // Returns true for empty containers.
4727 // O(n^2)
4728 template <typename Container, typename F>
all_unique_on(F f,const Container & xs)4729 bool all_unique_on(F f, const Container& xs)
4730 {
4731     return all_unique_by_eq(is_equal_by(f), xs);
4732 }
4733 
4734 // API search type: all_unique : [a] -> Bool
4735 // fwd bind count: 0
4736 // Checks if all elements in a container are unique.
4737 // Returns true for empty containers.
4738 // O(n^2)
4739 template <typename Container>
all_unique(const Container & xs)4740 bool all_unique(const Container& xs)
4741 {
4742     typedef typename Container::value_type T;
4743     auto comp = std::equal_to<T>();
4744     return all_unique_by_eq(comp, xs);
4745 }
4746 
4747 // API search type: is_strictly_sorted_by : (((a, a) -> Bool), [a]) -> Bool
4748 // fwd bind count: 1
4749 // Checks if a container already is strictly sorted using a predicate.
4750 // comp(a, b) must return true only if a < b.
4751 // O(n)
4752 template <typename Container, typename Compare>
is_strictly_sorted_by(Compare comp,const Container & xs)4753 bool is_strictly_sorted_by(Compare comp, const Container& xs)
4754 {
4755     internal::check_compare_for_container<Compare, Container>();
4756     if (size_of_cont(xs) < 2)
4757         return true;
4758     auto it1 = std::begin(xs);
4759     for (auto it2 = it1 + 1; it2 < std::end(xs); ++it1, ++it2)
4760         if (!internal::invoke(comp, *it1, *it2))
4761             return false;
4762     return true;
4763 }
4764 
4765 // API search type: is_strictly_sorted_on : ((a -> b), [a]) -> Bool
4766 // fwd bind count: 1
4767 // Checks if a container already is strictly sorted using a transformer.
4768 // O(n)
4769 template <typename Container, typename F>
is_strictly_sorted_on(F f,const Container & xs)4770 bool is_strictly_sorted_on(F f, const Container& xs)
4771 {
4772     return is_strictly_sorted_by(is_less_by(f), xs);
4773 }
4774 
4775 // API search type: is_strictly_sorted : [a] -> Bool
4776 // fwd bind count: 0
4777 // Checks if a container already is strictly sorted
4778 // in ascending order using std::less.
4779 // O(n)
4780 template <typename Container>
is_strictly_sorted(const Container & xs)4781 bool is_strictly_sorted(const Container& xs)
4782 {
4783     typedef typename Container::value_type T;
4784     auto comp = std::less<T>();
4785     return is_strictly_sorted_by(comp, xs);
4786 }
4787 
4788 // API search type: is_sorted_by : (((a, a) -> Bool), [a]) -> Bool
4789 // fwd bind count: 1
4790 // Checks if a container already is sorted using a predicate.
4791 // comp(a, b) must return true only if a < b.
4792 // O(n)
4793 template <typename Container, typename Compare>
is_sorted_by(Compare comp,const Container & xs)4794 bool is_sorted_by(Compare comp, const Container& xs)
4795 {
4796     internal::check_compare_for_container<Compare, Container>();
4797     if (size_of_cont(xs) < 2)
4798         return true;
4799     auto it1 = std::begin(xs);
4800     for (auto it2 = it1 + 1; it2 < std::end(xs); ++it1, ++it2)
4801         if (internal::invoke(comp, *it2, *it1))
4802             return false;
4803     return true;
4804 }
4805 
4806 // API search type: is_sorted_on : ((a -> b), [a]) -> Bool
4807 // fwd bind count: 1
4808 // Checks if a container already is strictly sorted using a transformer.
4809 // O(n)
4810 template <typename Container, typename F>
is_sorted_on(F f,const Container & xs)4811 bool is_sorted_on(F f, const Container& xs)
4812 {
4813     return is_sorted_by(is_less_by(f), xs);
4814 }
4815 
4816 // API search type: is_sorted : [a] -> Bool
4817 // fwd bind count: 0
4818 // Checks if a container already is sorted
4819 // in ascending order using std::less.
4820 // O(n)
4821 template <typename Container>
is_sorted(const Container & xs)4822 bool is_sorted(const Container& xs)
4823 {
4824     typedef typename Container::value_type T;
4825     auto comp = std::less<T>();
4826     return is_sorted_by(comp, xs);
4827 }
4828 
4829 // API search type: is_prefix_of : ([a], [a]) -> Bool
4830 // fwd bind count: 1
4831 // Checks if a containers starts with a token.
4832 // is_prefix_of("Fun", "FunctionalPlus") == true
4833 template <typename Container>
is_prefix_of(const Container & token,const Container & xs)4834 bool is_prefix_of(const Container& token, const Container& xs)
4835 {
4836     if (size_of_cont(token) > size_of_cont(xs))
4837         return false;
4838     return get_segment(0, size_of_cont(token), xs) == token;
4839 }
4840 
4841 // API search type: is_suffix_of : ([a], [a]) -> Bool
4842 // fwd bind count: 1
4843 // Checks if a containers contains a token as a segment.
4844 // is_suffix_of("us", "FunctionalPlus") == true
4845 template <typename Container>
is_suffix_of(const Container & token,const Container & xs)4846 bool is_suffix_of(const Container& token, const Container& xs)
4847 {
4848     if (size_of_cont(token) > size_of_cont(xs))
4849         return false;
4850     return get_segment(size_of_cont(xs) - size_of_cont(token),
4851         size_of_cont(xs), xs) == token;
4852 }
4853 
4854 // API search type: all_by : ((a -> Bool), [a]) -> Bool
4855 // fwd bind count: 1
4856 // Checks if a containers contains a token as a segment.
4857 // all_by(is_even, [2, 4, 6]) == true
4858 // Returns true for empty containers.
4859 template <typename UnaryPredicate, typename Container>
all_by(UnaryPredicate p,const Container & xs)4860 bool all_by(UnaryPredicate p, const Container& xs)
4861 {
4862     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
4863     return std::all_of(std::begin(xs), std::end(xs), p);
4864 }
4865 
4866 // API search type: all : [Bool] -> Bool
4867 // fwd bind count: 0
4868 // Checks if all values in a container evaluate to true.
4869 // all([true, false, true]) == false
4870 // Returns true for empty containers.
4871 template <typename Container>
all(const Container & xs)4872 bool all(const Container& xs)
4873 {
4874     typedef typename Container::value_type T;
4875     return all_by(identity<T>, xs);
4876 }
4877 
4878 // API search type: all_the_same_by : (((a, a) -> Bool), [a]) -> Bool
4879 // fwd bind count: 1
4880 // Checks if all values in a container are equal using a binary predicate.
4881 // Returns true for empty containers.
4882 template <typename Container, typename BinaryPredicate>
all_the_same_by(BinaryPredicate p,const Container & xs)4883 bool all_the_same_by(BinaryPredicate p, const Container& xs)
4884 {
4885     internal::check_binary_predicate_for_container<BinaryPredicate, Container>();
4886     if (size_of_cont(xs) < 2)
4887         return true;
4888     auto unaryPredicate = bind_1st_of_2(p, xs.front());
4889     return all_by(unaryPredicate, xs);
4890 }
4891 
4892 // API search type: all_the_same_on : ((a -> b), [a]) -> Bool
4893 // fwd bind count: 1
4894 // Checks if all values in a container are equal using a transformer.
4895 // Returns true for empty containers.
4896 template <typename Container, typename F>
all_the_same_on(F f,const Container & xs)4897 bool all_the_same_on(F f, const Container& xs)
4898 {
4899     if (size_of_cont(xs) < 2)
4900         return true;
4901     auto unaryPredicate = is_equal_by_to(f, f(xs.front()));
4902     return all_by(unaryPredicate, xs);
4903 }
4904 
4905 // API search type: all_the_same : [a] -> Bool
4906 // fwd bind count: 0
4907 // Checks if all values in a container are equal.
4908 // Returns true for empty containers.
4909 template <typename Container>
all_the_same(const Container & xs)4910 bool all_the_same(const Container& xs)
4911 {
4912     typedef typename Container::value_type T;
4913     auto binaryPredicate = std::equal_to<T>();
4914     return all_the_same_by(binaryPredicate, xs);
4915 }
4916 
4917 // API search type: numbers_step : (a, a, a) -> [a]
4918 // fwd bind count: 2
4919 // Return a sequence of numbers using a specific step.
4920 // numbers_step(2, 9, 2) == [2, 4, 6, 8]
4921 template <typename T,
4922         typename ContainerOut = std::vector<T>>
numbers_step(const T start,const T end,const T step)4923 ContainerOut numbers_step
4924         (const T start, const T end, const T step)
4925 {
4926     ContainerOut result;
4927     if ((step > 0 && start >= end) ||
4928         (step < 0 && start <= end) ||
4929         step == 0)
4930     {
4931         return result;
4932     }
4933     std::size_t size = static_cast<std::size_t>((end - start) / step);
4934     internal::prepare_container(result, size);
4935     auto it = internal::get_back_inserter<ContainerOut>(result);
4936     for (T x = start; x < end; x += step)
4937         *it = x;
4938     return result;
4939 }
4940 
4941 // API search type: numbers : (a, a) -> [a]
4942 // fwd bind count: 1
4943 // Return an ascending sequence of numbers..
4944 // Also known as range.
4945 // numbers(2, 9) == [2, 3, 4, 5, 6, 7, 8]
4946 template <typename T,
4947         typename ContainerOut = std::vector<T>>
numbers(const T start,const T end)4948 ContainerOut numbers(const T start, const T end)
4949 {
4950     return numbers_step<T, ContainerOut>(start, end, 1);
4951 }
4952 
4953 // API search type: singleton_seq : a -> [a]
4954 // fwd bind count: 0
4955 // Construct a sequence containing a single value.
4956 // singleton_seq(3) == [3].
4957 template <typename T, typename ContainerOut = std::vector<T>>
singleton_seq(const T & x)4958 ContainerOut singleton_seq(const T& x)
4959 {
4960     return ContainerOut(1, x);
4961 }
4962 
4963 // API search type: all_idxs : [a] -> [Int]
4964 // fwd bind count: 0
4965 // Returns a vector containing all valid indices of sequence xs.
4966 // all_idxs([6,4,7,6]) == [0,1,2,3]
4967 template <typename Container>
all_idxs(const Container & xs)4968 std::vector<std::size_t> all_idxs(const Container& xs)
4969 {
4970     return numbers<std::size_t>(0, size_of_cont(xs));
4971 }
4972 
4973 // API search type: init : [a] -> [a]
4974 // fwd bind count: 0
4975 // init([0,1,2,3]) == [0,1,2]
4976 // Unsafe! xs must be non-empty.
4977 template <typename Container,
4978     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
init(Container && xs)4979 ContainerOut init(Container&& xs)
4980 {
4981     assert(!is_empty(xs));
4982     return get_segment(0, size_of_cont(std::forward<Container>(xs)) - 1, xs);
4983 }
4984 
4985 // API search type: tail : [a] -> [a]
4986 // fwd bind count: 0
4987 // Drops the first element of a container, keeps the rest. Unsafe!
4988 // tail([0,1,2,3]) == [1,2,3]
4989 // Unsafe! xs must be non-empty.
4990 template <typename Container,
4991     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
tail(Container && xs)4992 ContainerOut tail(Container&& xs)
4993 {
4994     assert(!is_empty(xs));
4995     return get_segment(1, size_of_cont(std::forward<Container>(xs)), xs);
4996 }
4997 
4998 // API search type: head : [a] -> a
4999 // fwd bind count: 0
5000 // Return the first element of a container.
5001 // head([0,1,2,3]) == 0
5002 // Unsafe! xs must be non-empty.
5003 template <typename Container>
head(const Container & xs)5004 typename Container::value_type head(const Container& xs)
5005 {
5006     assert(!is_empty(xs));
5007     return xs.front();
5008 }
5009 
5010 // API search type: last : [a] -> a
5011 // fwd bind count: 0
5012 // Return the last element of a container.
5013 // last([0,1,2,3]) == 3
5014 // Unsafe! xs must be non-empty.
5015 template <typename Container>
last(const Container & xs)5016 typename Container::value_type last(const Container& xs)
5017 {
5018     assert(!is_empty(xs));
5019     return xs.back();
5020 }
5021 
5022 // API search type: mean_stddev : [a] -> (a, a)
5023 // fwd bind count: 0
5024 // Calculates the mean and the population standard deviation.
5025 // mean_stddev([4, 8]) == (6, 2)
5026 // mean_stddev([1, 3, 7, 4]) == (3.75, 2.5)
5027 // xs must be non-empty.
5028 template <typename Result, typename Container>
mean_stddev(const Container & xs)5029 std::pair<Result, Result> mean_stddev(const Container& xs)
5030 {
5031     assert(size_of_cont(xs) != 0);
5032 
5033     // http://stackoverflow.com/a/7616783/1866775
5034     Result sum = static_cast<Result>(
5035         internal::accumulate(xs.begin(), xs.end(),
5036             static_cast<typename Container::value_type>(0)));
5037     Result mean = sum / static_cast<Result>(xs.size());
5038 
5039     std::vector<Result> diff(xs.size());
5040     std::transform(xs.begin(), xs.end(), diff.begin(),
5041         [mean](Result x)
5042         {
5043             return x - mean;
5044         });
5045     Result sq_sum = std::inner_product(
5046         diff.begin(), diff.end(), diff.begin(), static_cast<Result>(0));
5047     Result stddev = std::sqrt(sq_sum / static_cast<Result>(xs.size()));
5048     return std::make_pair(mean, stddev);
5049 }
5050 
5051 // API search type: count_occurrences_by : ((a -> b), [a]) -> Map b Int
5052 // fwd bind count: 1
5053 // Returns a discrete frequency distribution of the elements in a container
5054 // applying a specific transformer.
5055 // count_occurrences_by(floor, [1.1, 2.3, 2.7, 3.6, 2.4]) == [(1, 1), (2, 3), (3, 1)]
5056 // O(n)
5057 template <typename F, typename ContainerIn>
count_occurrences_by(F f,const ContainerIn & xs)5058 auto count_occurrences_by(F f, const ContainerIn& xs)
5059 {
5060     using In = typename ContainerIn::value_type;
5061     using MapOut =
5062         std::map<std::decay_t<internal::invoke_result_t<F, In>>, std::size_t>;
5063 
5064     internal::trigger_static_asserts<internal::unary_function_tag, F, typename ContainerIn::value_type>();
5065     MapOut result;
5066     for (const auto& x : xs)
5067     {
5068         ++result[internal::invoke(f, x)];
5069     }
5070     return result;
5071 }
5072 
5073 // API search type: count_occurrences : [a] -> Map a Int
5074 // fwd bind count: 0
5075 // Returns a discrete frequency distribution of the elements in a container
5076 // applying a specific transformer.
5077 // Can be used to create a histogram.
5078 // count_occurrences([1,2,2,3,2]) == [(1, 1), (2, 3), (3, 1)]
5079 // O(n)
5080 template <typename ContainerIn,
5081         typename MapOut = typename std::map<
5082             typename ContainerIn::value_type, std::size_t>>
count_occurrences(const ContainerIn & xs)5083 MapOut count_occurrences(const ContainerIn& xs)
5084 {
5085     return count_occurrences_by(identity<typename ContainerIn::value_type>, xs);
5086 }
5087 
5088 // API search type: lexicographical_less_by : (((a, a) -> Bool), [a], [a]) -> Bool
5089 // fwd bind count: 2
5090 // Lexicographical less-than comparison using a specific predicate.
5091 // lexicographical_less_by((<), [0,1,2,2,4,5], [0,1,2,3,4,5]) == true
5092 // lexicographical_less_by((<), "012245", "012345") == true
5093 // lexicographical_less_by((<), "01234", "012345") == true
5094 // lexicographical_less_by((<), "012345", "01234") == false
5095 // lexicographical_less_by((<), "012345", "012345") == false
5096 template <typename Container, typename BinaryPredicate>
lexicographical_less_by(BinaryPredicate p,const Container & xs,const Container & ys)5097 bool lexicographical_less_by(BinaryPredicate p,
5098         const Container& xs, const Container& ys)
5099 {
5100     internal::check_binary_predicate_for_container<BinaryPredicate, Container>();
5101     auto itXs = std::begin(xs);
5102     auto itYs = std::begin(ys);
5103     while (itXs != std::end(xs) && itYs != std::end(ys))
5104     {
5105         if (internal::invoke(p, *itXs, *itYs))
5106         {
5107             return true;
5108         }
5109         if (internal::invoke(p, *itYs, *itXs))
5110         {
5111             return false;
5112         }
5113         ++itXs;
5114         ++itYs;
5115     }
5116     if (size_of_cont(xs) < size_of_cont(ys))
5117     {
5118         return true;
5119     }
5120     return false;
5121 }
5122 
5123 // API search type: lexicographical_less : ([a], [a]) -> Bool
5124 // fwd bind count: 1
5125 // Lexicographical less-than comparison.
5126 // lexicographical_less([0,1,2,2,4,5], [0,1,2,3,4,5]) == true
5127 // lexicographical_less("012245", "012345") == true
5128 // lexicographical_less("01234", "012345") == true
5129 // lexicographical_less("012345", "01234") == false
5130 // lexicographical_less("012345", "012345") == false
5131 template <typename Container>
lexicographical_less(const Container & xs,const Container & ys)5132 bool lexicographical_less(const Container& xs, const Container& ys)
5133 {
5134     return lexicographical_less_by(
5135         is_less<typename Container::value_type>, xs, ys);
5136 }
5137 
5138 // API search type: lexicographical_sort : [[a]] -> [[a]]
5139 // fwd bind count: 0
5140 // sort by lexicographical_less
5141 template <typename Container,
5142     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
lexicographical_sort(Container && xs)5143 ContainerOut lexicographical_sort(Container&& xs)
5144 {
5145     typedef typename std::remove_reference<Container>::type::value_type T;
5146     return sort_by(lexicographical_less<T>, std::forward<Container>(xs));
5147 }
5148 
5149 // API search type: replicate : (Int, a) -> [a]
5150 // fwd bind count: 1
5151 // Create a sequence containing x n times.
5152 // replicate(3, 1) == [1, 1, 1]
5153 template <typename T,
5154         typename ContainerOut = std::vector<T>>
replicate(std::size_t n,const T & x)5155 ContainerOut replicate(std::size_t n, const T& x)
5156 {
5157     return ContainerOut(n, x);
5158 }
5159 
5160 namespace internal
5161 {
5162 
5163 template <typename UnaryPredicate, typename T>
instead_of_if(internal::reuse_container_t,UnaryPredicate pred,const T & alt,T && x)5164 T instead_of_if(internal::reuse_container_t, UnaryPredicate pred,
5165     const T& alt, T&& x)
5166 {
5167     if (internal::invoke(pred, x))
5168         return alt;
5169     else
5170         return std::forward<T>(x);
5171 }
5172 
5173 template <typename UnaryPredicate, typename T>
instead_of_if(internal::create_new_container_t,UnaryPredicate pred,const T & alt,const T & x)5174 T instead_of_if(internal::create_new_container_t, UnaryPredicate pred,
5175     const T& alt, const T& x)
5176 {
5177     if (internal::invoke(pred, x))
5178         return alt;
5179     else
5180         return x;
5181 }
5182 
5183 } // namespace internal
5184 
5185 // API search type: instead_of_if : ((a -> Bool), a, a) -> a
5186 // fwd bind count: 2
5187 // Return alt if pred(x), otherwise x itself.
5188 template <typename UnaryPredicate, typename T, typename TAlt>
instead_of_if(UnaryPredicate pred,const TAlt & alt,T && x)5189 auto instead_of_if(UnaryPredicate pred, const TAlt& alt, T&& x)
5190 {
5191     return internal::instead_of_if(internal::can_reuse_v<T>{},
5192         pred, alt, std::forward<T>(x));
5193 }
5194 
5195 // API search type: instead_of_if_empty : ((a -> Bool), [a], [a]) -> [a]
5196 // fwd bind count: 2
5197 // Return alt if xs is empty, otherwise xs itself.
5198 template <typename Container, typename ContainerAlt,
5199     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
instead_of_if_empty(const ContainerAlt & alt,Container && xs)5200 ContainerOut instead_of_if_empty(const ContainerAlt& alt, Container&& xs)
5201 {
5202     return instead_of_if(
5203         is_empty<internal::remove_const_and_ref_t<Container>>,
5204         alt, std::forward<Container>(xs));
5205 }
5206 
5207 } // namespace fplus
5208 
5209 //
5210 // container_properties.hpp
5211 //
5212 
5213 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
5214 // https://github.com/Dobiasd/FunctionalPlus
5215 // Distributed under the Boost Software License, Version 1.0.
5216 // (See accompanying file LICENSE_1_0.txt or copy at
5217 //  http://www.boost.org/LICENSE_1_0.txt)
5218 
5219 
5220 
5221 //
5222 // generate.hpp
5223 //
5224 
5225 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
5226 // https://github.com/Dobiasd/FunctionalPlus
5227 // Distributed under the Boost Software License, Version 1.0.
5228 // (See accompanying file LICENSE_1_0.txt or copy at
5229 //  http://www.boost.org/LICENSE_1_0.txt)
5230 
5231 
5232 
5233 //
5234 // filter.hpp
5235 //
5236 
5237 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
5238 // https://github.com/Dobiasd/FunctionalPlus
5239 // Distributed under the Boost Software License, Version 1.0.
5240 // (See accompanying file LICENSE_1_0.txt or copy at
5241 //  http://www.boost.org/LICENSE_1_0.txt)
5242 
5243 
5244 
5245 //
5246 // result.hpp
5247 //
5248 
5249 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
5250 // https://github.com/Dobiasd/FunctionalPlus
5251 // Distributed under the Boost Software License, Version 1.0.
5252 // (See accompanying file LICENSE_1_0.txt or copy at
5253 //  http://www.boost.org/LICENSE_1_0.txt)
5254 
5255 
5256 
5257 
5258 #include <cassert>
5259 #include <functional>
5260 #include <memory>
5261 
5262 namespace fplus
5263 {
5264 
5265 template <typename Ok, typename Error>
5266 class result;
5267 
5268 template <typename Ok, typename Error>
5269 result<Ok, Error> ok(const Ok& val);
5270 
5271 template <typename Ok, typename Error>
5272 result<Ok, Error> error(const Error& error);
5273 
5274 // Can hold a value of type Ok or an error of type Error.
5275 template <typename Ok, typename Error>
5276 class result
5277 {
5278 public:
is_ok() const5279     bool is_ok() const { return static_cast<bool>(ptr_ok_); }
is_error() const5280     bool is_error() const { return static_cast<bool>(ptr_error_); }
unsafe_get_ok() const5281     const Ok& unsafe_get_ok() const {
5282         check_either_or_invariant(); assert(is_ok()); return *ptr_ok_;
5283     }
unsafe_get_error() const5284     const Error& unsafe_get_error() const {
5285         check_either_or_invariant(); assert(is_error()); return *ptr_error_;
5286     }
5287     typedef Ok ok_t;
5288     typedef Error error_t;
5289 
result(const result<Ok,Error> & other)5290     result(const result<Ok, Error>& other) :
5291         ptr_ok_(other.is_ok() ? ptr_ok(new Ok(other.unsafe_get_ok())) : ptr_ok()),
5292         ptr_error_(other.is_error() ? ptr_error(new Error(other.unsafe_get_error())) : ptr_error())
5293     {
5294         check_either_or_invariant();
5295     }
operator =(const result<Ok,Error> & other)5296     result<Ok, Error>& operator = (const result<Ok, Error>& other)
5297     {
5298         ptr_ok_ = other.is_ok() ? ptr_ok(new Ok(other.unsafe_get_ok())) : ptr_ok();
5299         ptr_error_ = other.is_error() ? ptr_error(new Error(other.unsafe_get_error())) : ptr_error();
5300         return *this;
5301     }
5302 private:
check_either_or_invariant() const5303     void check_either_or_invariant() const
5304     {
5305         assert(is_ok() != is_error());
5306     }
result()5307     result() : ptr_ok_(ptr_ok()), ptr_error_(ptr_error()) {}
5308     typedef std::unique_ptr<Ok> ptr_ok;
5309     typedef std::unique_ptr<Error> ptr_error;
5310     friend result<Ok, Error> ok<Ok, Error>(const Ok& ok);
5311     friend result<Ok, Error> error<Ok, Error>(const Error& error);
5312     ptr_ok ptr_ok_;
5313     ptr_error ptr_error_;
5314 };
5315 
5316 // API search type: is_ok : Result a b -> Bool
5317 // fwd bind count: 0
5318 // Is not error?
5319 template <typename Ok, typename Error>
is_ok(const result<Ok,Error> & result)5320 bool is_ok(const result<Ok, Error>& result)
5321 {
5322     return result.is_ok();
5323 }
5324 
5325 // API search type: is_error : Result a b -> Bool
5326 // fwd bind count: 0
5327 // Is not OK?
5328 template <typename Ok, typename Error>
is_error(const result<Ok,Error> & result)5329 bool is_error(const result<Ok, Error>& result)
5330 {
5331     return !is_ok(result);
5332 }
5333 
5334 // API search type: unsafe_get_ok : Result a b -> a
5335 // fwd bind count: 0
5336 // Crashes if result is error!
5337 template <typename Ok, typename Error>
5338 Ok unsafe_get_ok(const result<Ok, Error>& result)
5339 {
5340     return result.unsafe_get_ok();
5341 }
5342 
5343 // API search type: unsafe_get_error : Result a b -> b
5344 // fwd bind count: 0
5345 // Crashes if result is ok!
5346 template <typename Ok, typename Error>
unsafe_get_error(const result<Ok,Error> & result)5347 Error unsafe_get_error(const result<Ok, Error>& result)
5348 {
5349     return result.unsafe_get_error();
5350 }
5351 
5352 // API search type: ok_with_default : (a, Result a b) -> a
5353 // fwd bind count: 1
5354 // Get the value from a result or the default in case it is error.
5355 template <typename Ok, typename Error>
5356 Ok ok_with_default(const Ok& defaultValue, const result<Ok, Error>& result)
5357 {
5358     if (is_ok(result))
5359         return unsafe_get_ok(result);
5360     return defaultValue;
5361 }
5362 
5363 // API search type: ok : a -> Result a b
5364 // fwd bind count: 0
5365 // Wrap a value in a result as a Ok.
5366 template <typename Ok, typename Error>
ok(const Ok & val)5367 result<Ok, Error> ok(const Ok& val)
5368 {
5369     result<Ok, Error> x;
5370     x.ptr_ok_.reset(new Ok(val));
5371     return x;
5372 }
5373 
5374 // API search type: error : b -> Result a b
5375 // fwd bind count: 0
5376 // Construct an error of a certain result type.
5377 template <typename Ok, typename Error>
error(const Error & error)5378 result<Ok, Error> error(const Error& error)
5379 {
5380     result<Ok, Error> x;
5381     x.ptr_error_.reset(new Error(error));
5382     return x;
5383 }
5384 
5385 // API search type: to_maybe : Result a b -> Maybe a
5386 // fwd bind count: 0
5387 // Convert ok to just, error to nothing.
5388 template <typename Ok, typename Error>
to_maybe(const result<Ok,Error> & result)5389 maybe<Ok> to_maybe(const result<Ok, Error>& result)
5390 {
5391     if (is_ok(result))
5392         return just<Ok>(unsafe_get_ok(result));
5393     else
5394         return nothing<Ok>();
5395 }
5396 
5397 // API search type: from_maybe : (b, Maybe a) -> Result a b
5398 // fwd bind count: 1
5399 // Convert just to ok, nothing to error.
5400 template <typename Error, typename Ok>
from_maybe(const Error & err,const maybe<Ok> & maybe)5401 result<Ok, Error> from_maybe(const Error& err, const maybe<Ok>& maybe)
5402 {
5403     if (is_just(maybe))
5404         return ok<Ok, Error>(unsafe_get_just(maybe));
5405     else
5406         return error<Ok, Error>(err);
5407 }
5408 
5409 // API search type: throw_on_error : (e, Result a b) -> a
5410 // fwd bind count: 1
5411 // Throws the given exception in case of error.
5412 // Return ok value if ok.
5413 template <typename E, typename Ok, typename Error>
5414 Ok throw_on_error(const E& e, const result<Ok, Error>& result)
5415 {
5416     if (is_error(result))
5417         throw e;
5418     return unsafe_get_ok(result);
5419 }
5420 
5421 // API search type: throw_type_on_error : Result a b -> a
5422 // Throws the given exception type constructed with error value if error.
5423 // Return ok value if ok.
5424 template <typename E, typename Ok, typename Error>
5425 Ok throw_type_on_error(const result<Ok, Error>& result)
5426 {
5427     if (is_error(result))
5428         throw E(unsafe_get_error(result));
5429     return unsafe_get_ok(result);
5430 }
5431 
5432 // True if ok values are the same or if errors are the same.
5433 template <typename Ok, typename Error>
operator ==(const result<Ok,Error> & x,const result<Ok,Error> & y)5434 bool operator == (const result<Ok, Error>& x, const result<Ok, Error>& y)
5435 {
5436     if (is_ok(x) && is_ok(y))
5437         return unsafe_get_ok(x) == unsafe_get_ok(y);
5438     if (is_error(x) && is_error(y))
5439         return unsafe_get_error(x) == unsafe_get_error(y);
5440     return false;
5441 }
5442 
5443 // False if ok values are the same or if both errors are the same.
5444 template <typename Ok, typename Error>
operator !=(const result<Ok,Error> & x,const result<Ok,Error> & y)5445 bool operator != (const result<Ok, Error>& x, const result<Ok, Error>& y)
5446 {
5447     return !(x == y);
5448 }
5449 
5450 // API search type: lift_result : ((a -> b), Result a c) -> Result b c
5451 // fwd bind count: 1
5452 // Lifts a function into the result functor.
5453 // A function that for example was able to convert and int into a string,
5454 // now can convert a result<int, Err> into a result<string, Err>.
5455 // An error stays the same error, regardless of the conversion.
5456 template <typename Error, typename F, typename A>
lift_result(F f,const result<A,Error> & r)5457 auto lift_result(F f, const result<A, Error>& r)
5458 {
5459     internal::trigger_static_asserts<internal::unary_function_tag, F, A>();
5460 
5461     using B = std::decay_t<internal::invoke_result_t<F, A>>;
5462 
5463     if (is_ok(r))
5464         return ok<B, Error>(internal::invoke(f, unsafe_get_ok(r)));
5465     return error<B, Error>(unsafe_get_error(r));
5466 }
5467 
5468 // API search type: lift_result_both : ((a -> c), (b -> d), Result a b) -> Result c d
5469 // fwd bind count: 2
5470 // Lifts two functions into the result functor.
5471 template <typename F, typename G, typename A, typename B>
lift_result_both(F f,G g,const result<A,B> & r)5472 auto lift_result_both(F f, G g, const result<A, B>& r)
5473 {
5474     internal::trigger_static_asserts<internal::unary_function_tag, F, A>();
5475     internal::trigger_static_asserts<internal::unary_function_tag, G, B>();
5476 
5477     using C = std::decay_t<internal::invoke_result_t<F, A>>;
5478     using D = std::decay_t<internal::invoke_result_t<G, B>>;
5479 
5480     if (is_ok(r))
5481         return ok<C, D>(internal::invoke(f, unsafe_get_ok(r)));
5482     return error<C, D>(internal::invoke(g, unsafe_get_error(r)));
5483 }
5484 
5485 // API search type: unify_result : ((a -> c), (b -> c), Result a b) -> c
5486 // fwd bind count: 2
5487 // Extracts the value (Ok or Error) from a Result
5488 // as defined by the two given functions.
5489 template <typename F, typename G, typename A, typename B>
unify_result(F f,G g,const result<A,B> & r)5490 auto unify_result(F f, G g, const result<A, B>& r)
5491 {
5492     internal::trigger_static_asserts<internal::unary_function_tag, F, A>();
5493     internal::trigger_static_asserts<internal::unary_function_tag, G, B>();
5494     static_assert(std::is_same<internal::invoke_result_t<F, A>,
5495                                internal::invoke_result_t<G, B>>::value,
5496                   "Both functions must return the same type.");
5497     if (is_ok(r))
5498         return internal::invoke(f, unsafe_get_ok(r));
5499     return internal::invoke(g, unsafe_get_error(r));
5500 }
5501 
5502 // API search type: join_result : Result (Result a b) b -> Result a b
5503 // Flattens a nested result.
5504 // join_result(Ok Ok x) == Ok x
5505 // join_result(Ok Error e) == Error e
5506 // join_result(Error e) == Error e
5507 template <typename OK, typename Error>
join_result(const result<result<OK,Error>,Error> & r)5508 result<OK, Error> join_result(const result<result<OK, Error>, Error>& r)
5509 {
5510     if (is_ok(r))
5511         return unsafe_get_ok(r);
5512     else
5513         return error<OK, Error>(r.unsafe_get_error());
5514 }
5515 
5516 // API search type: and_then_result : ((a -> Result c b), (Result a b)) -> Result c b
5517 // fwd bind count: 1
5518 // Monadic bind.
5519 // Returns the error if the result is an error.
5520 // Otherwise return the result of applying
5521 // the function to the ok value of the result.
5522 template <typename Ok, typename Error, typename F>
and_then_result(F f,const result<Ok,Error> & r)5523 auto and_then_result(F f, const result<Ok, Error>& r)
5524 {
5525     internal::trigger_static_asserts<internal::unary_function_tag, F, Ok>();
5526 
5527     using FOut = std::decay_t<internal::invoke_result_t<F, Ok>>;
5528     static_assert(std::is_same<Error, typename FOut::error_t>::value,
5529                   "Error type must stay the same.");
5530     if (is_ok(r))
5531         return internal::invoke(f, unsafe_get_ok(r));
5532     else
5533         return error<typename FOut::ok_t, typename FOut::error_t>(r.unsafe_get_error());
5534 }
5535 
5536 // API search type: compose_result : ((a -> Result b c), (b -> Result d c)) -> (a -> Result d c)
5537 // Left-to-right Kleisli composition of monads.
5538 // It is possible to compose a variadic number of callables.
5539 // The first callable can take a variadic number of parameters.
5540 template <typename... Callables>
compose_result(Callables &&...callables)5541 auto compose_result(Callables&&... callables)
5542 {
5543     auto bind_result = [](auto f, auto g) {
5544         return [f = std::move(f), g = std::move(g)](auto&&... args)
5545         {
5546             internal::trigger_static_asserts<internal::check_arity_tag,
5547                                                  decltype(f),
5548                                                  decltype(args)...>();
5549 #if defined(_MSC_VER) && _MSC_VER >= 1920 // in VS2019, compilation with /permissive- breaks with 'using' syntax below
5550             struct FOut : std::decay_t<
5551                 internal::invoke_result_t<decltype(f), decltype(args)...>> {};
5552 #else
5553             using FOut = std::decay_t<
5554                 internal::invoke_result_t<decltype(f), decltype(args)...>>;
5555 #endif
5556 
5557             internal::trigger_static_asserts<internal::unary_function_tag,
5558                                                  decltype(g),
5559                                                  typename FOut::ok_t>();
5560 #if defined(_MSC_VER) && _MSC_VER >= 1920 // in VS2019, compilation with /permissive- breaks with 'using' syntax below
5561             struct GOut : std::decay_t<
5562                 internal::invoke_result_t<decltype(g), typename FOut::ok_t>> {};
5563 #else
5564             using GOut = std::decay_t<
5565                 internal::invoke_result_t<decltype(g), typename FOut::ok_t>>;
5566 #endif
5567             static_assert(std::is_same<typename FOut::error_t,
5568                                        typename GOut::error_t>::value,
5569                           "Error type must stay the same.");
5570 
5571             auto resultB =
5572                 internal::invoke(f, std::forward<decltype(args)>(args)...);
5573             if (is_ok(resultB))
5574                 return internal::invoke(g, unsafe_get_ok(resultB));
5575             return error<typename GOut::ok_t, typename GOut::error_t>(
5576                 unsafe_get_error(resultB));
5577         };
5578     };
5579     return internal::compose_binary_lift(bind_result,
5580                                        std::forward<Callables>(callables)...);
5581 }
5582 } // namespace fplus
5583 
5584 #include <algorithm>
5585 
5586 namespace fplus
5587 {
5588 
5589 namespace internal
5590 {
5591 
5592 template <typename Pred, typename Container>
keep_if(internal::reuse_container_t,Pred pred,Container && xs)5593 Container keep_if(internal::reuse_container_t, Pred pred, Container&& xs)
5594 {
5595     internal::check_unary_predicate_for_container<Pred, Container>();
5596     xs.erase(std::remove_if(
5597         std::begin(xs), std::end(xs), logical_not(pred)), std::end(xs));
5598     return std::forward<Container>(xs);
5599 }
5600 
5601 template <typename Pred, typename Container>
keep_if(internal::create_new_container_t,Pred pred,const Container & xs)5602 Container keep_if(internal::create_new_container_t, Pred pred,
5603     const Container& xs)
5604 {
5605     internal::check_unary_predicate_for_container<Pred, Container>();
5606     Container result;
5607     auto it = internal::get_back_inserter<Container>(result);
5608     std::copy_if(std::begin(xs), std::end(xs), it, pred);
5609     return result;
5610 }
5611 
5612 } // namespace internal
5613 
5614 // API search type: keep_if : ((a -> Bool), [a]) -> [a]
5615 // fwd bind count: 1
5616 // Keep the elements of a sequence fulfilling a predicate.
5617 // keep_if(is_even, [1, 2, 3, 2, 4, 5]) == [2, 2, 4]
5618 // Also known as filter.
5619 template <typename Pred, typename Container,
5620     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
keep_if(Pred pred,Container && xs)5621 ContainerOut keep_if(Pred pred, Container&& xs)
5622 {
5623     return internal::keep_if(internal::can_reuse_v<Container>{},
5624         pred, std::forward<Container>(xs));
5625 }
5626 
5627 // API search type: drop_if : ((a -> Bool), [a]) -> [a]
5628 // fwd bind count: 1
5629 // Drop the elements of a sequence fulfilling a predicate.
5630 // drop_if(is_even, [1, 2, 3, 2, 4, 5]) == [1, 3, 5]
5631 // Also known as reject.
5632 template <typename Pred, typename Container,
5633     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
drop_if(Pred pred,Container && xs)5634 ContainerOut drop_if(Pred pred, Container&& xs)
5635 {
5636     return keep_if(logical_not(pred), std::forward<Container>(xs));
5637 }
5638 
5639 // API search type: without : (a, [a]) -> [a]
5640 // fwd bind count: 1
5641 // Keep all elements a sequence not equal to elem.
5642 // without(0, [1, 0, 0, 5, 3, 0, 1]) == [1, 5, 3, 1]
5643 template <typename Container,
5644     typename T = typename Container::value_type,
5645     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
without(T elem,Container && xs)5646 ContainerOut without(T elem, Container&& xs)
5647 {
5648     return drop_if(is_equal_to(elem), std::forward<Container>(xs));
5649 }
5650 
5651 // API search type: without_any : (a, [a]) -> [a]
5652 // fwd bind count: 1
5653 // Keep all elements a sequence not present in elems.
5654 // without([0, 1], [1, 0, 0, 5, 3, 0, 1]) == [5, 3]
5655 template <typename Container, typename ContainerElems,
5656     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
without_any(const ContainerElems & elems,Container && xs)5657 ContainerOut without_any(const ContainerElems& elems, Container&& xs)
5658 {
5659     static_assert(std::is_same<
5660         typename ContainerElems::value_type,
5661         typename std::remove_reference<Container>::type::value_type>::value,
5662         "Container values must be of the same type.");
5663     const auto pred = bind_2nd_of_2(is_elem_of<ContainerElems>, elems);
5664     return drop_if(pred, std::forward<Container>(xs));
5665 }
5666 
5667 // API search type: keep_if_with_idx : (((Int, a) -> Bool), [a]) -> [a]
5668 // fwd bind count: 1
5669 // Keep the elements of a sequence fulfilling a predicate.
5670 // Predicate takes index and value.
5671 // All elements fulfilling the predicate are kept.
5672 template <typename Pred, typename Container>
keep_if_with_idx(Pred pred,const Container & xs)5673 Container keep_if_with_idx(Pred pred, const Container& xs)
5674 {
5675     internal::check_index_with_type_predicate_for_container<Pred, Container>();
5676     Container ys;
5677     auto it = internal::get_back_inserter<Container>(ys);
5678     std::size_t idx = 0;
5679     for (const auto& x : xs)
5680     {
5681         if (internal::invoke(pred, idx++, x))
5682             *it = x;
5683     }
5684     return ys;
5685 }
5686 
5687 // API search type: drop_if_with_idx : (((Int, a) -> Bool), [a]) -> [a]
5688 // fwd bind count: 1
5689 // Drop the elements of a sequence fulfilling a predicate.
5690 // Predicate takes index and value.
5691 // All elements fulfilling the predicate are skipped.
5692 template <typename Pred, typename Container>
drop_if_with_idx(Pred pred,const Container & xs)5693 Container drop_if_with_idx(Pred pred, const Container& xs)
5694 {
5695     internal::check_index_with_type_predicate_for_container<Pred, Container>();
5696     const auto inverse_pred = [pred](auto idx, const auto& x)
5697     {
5698         return !internal::invoke(pred, idx, x);
5699     };
5700     return keep_if_with_idx(inverse_pred, xs);
5701 }
5702 
5703 namespace internal
5704 {
5705 
5706 template <typename UnaryPredicate, typename Container>
keep_by_idx(internal::reuse_container_t,UnaryPredicate pred,Container && xs)5707 Container keep_by_idx(internal::reuse_container_t,
5708     UnaryPredicate pred, Container&& xs)
5709 {
5710     auto itOut = std::begin(xs);
5711     std::size_t i = 0;
5712     for (auto it = std::begin(xs); it != std::end(xs); ++it)
5713     {
5714         if (internal::invoke(pred, i++))
5715             assign(*itOut++, std::move(*it));
5716     }
5717     xs.erase(itOut, std::end(xs));
5718     return std::forward<Container>(xs);
5719 }
5720 
5721 template <typename UnaryPredicate, typename Container>
keep_by_idx(internal::create_new_container_t,UnaryPredicate pred,const Container & xs)5722 Container keep_by_idx(internal::create_new_container_t,
5723     UnaryPredicate pred, const Container& xs)
5724 {
5725     Container ys = xs;
5726     return internal::keep_by_idx(internal::reuse_container_t(),
5727         pred, std::move(ys));
5728 }
5729 
5730 } // namespace internal
5731 
5732 // API search type: keep_by_idx : ((Int -> Bool), [a]) -> [a]
5733 // fwd bind count: 1
5734 // Keep the elements of a sequence with an index fulfilling a predicate.
5735 // Predicate takes an index and decides if an element is kept.
5736 template <typename UnaryPredicate, typename Container,
5737     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
keep_by_idx(UnaryPredicate pred,Container && xs)5738 ContainerOut keep_by_idx(UnaryPredicate pred, Container&& xs)
5739 {
5740     internal::check_unary_predicate_for_type<UnaryPredicate, std::size_t>();
5741     return internal::keep_by_idx(internal::can_reuse_v<Container>{},
5742         pred, std::forward<Container>(xs));
5743 }
5744 
5745 // API search type: drop_by_idx : ((Int -> Bool), [a]) -> [a]
5746 // fwd bind count: 1
5747 // Drop the elements of a sequence with an index fulfilling a predicate.
5748 // Predicate takes an index and decides if an element is dropped.
5749 template <typename UnaryPredicate, typename Container,
5750     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
drop_by_idx(UnaryPredicate pred,Container && xs)5751 ContainerOut drop_by_idx(UnaryPredicate pred, Container&& xs)
5752 {
5753     internal::check_unary_predicate_for_type<UnaryPredicate, std::size_t>();
5754     return keep_by_idx(logical_not(pred), std::forward<Container>(xs));
5755 }
5756 
5757 // API search type: keep_idxs : ([Int], [a]) -> [a]
5758 // fwd bind count: 1
5759 // Keep the elements of a sequence with an index present in idxs_to_keep.
5760 // keep_idxs([2,5], [1,2,3,4,5,6,7]) == [3,6]
5761 template <typename ContainerIdxs, typename Container>
keep_idxs(const ContainerIdxs & idxs_to_keep,const Container & xs)5762 Container keep_idxs(const ContainerIdxs& idxs_to_keep, const Container& xs)
5763 {
5764     static_assert(std::is_same<typename ContainerIdxs::value_type, std::size_t>::value,
5765         "Indices must be std::size_t");
5766     auto idxs_left = convert_container<std::list<std::size_t>>(
5767         unique(sort(idxs_to_keep)));
5768     Container ys;
5769     auto it = internal::get_back_inserter<Container>(ys);
5770     std::size_t idx = 0;
5771     for (const auto& x : xs)
5772     {
5773         if (!idxs_left.empty() && idxs_left.front() == idx)
5774         {
5775             idxs_left.pop_front();
5776             *it = x;
5777         }
5778         ++idx;
5779     }
5780     return ys;
5781 }
5782 
5783 // API search type: drop_idxs : ([Int], [a]) -> [a]
5784 // fwd bind count: 1
5785 // Drop the elements of a sequence with an index present in idxs_to_keep.
5786 // drop_idxs([2,5], [1,2,3,4,5,6,7]) == [1,2,4,5,7]
5787 template <typename ContainerIdxs, typename Container>
drop_idxs(const ContainerIdxs & idxs_to_drop,const Container & xs)5788 Container drop_idxs(const ContainerIdxs& idxs_to_drop, const Container& xs)
5789 {
5790     static_assert(std::is_same<typename ContainerIdxs::value_type, std::size_t>::value,
5791         "Indices must be std::size_t");
5792     auto idxs_left = convert_container<std::list<std::size_t>>(
5793         unique(sort(idxs_to_drop)));
5794     Container ys;
5795     auto it = internal::get_back_inserter<Container>(ys);
5796     std::size_t idx = 0;
5797     for (const auto& x : xs)
5798     {
5799         if (idxs_left.empty() || idxs_left.front() != idx)
5800         {
5801             *it = x;
5802         }
5803         else
5804         {
5805             if (!idxs_left.empty())
5806             {
5807                 idxs_left.pop_front();
5808             }
5809         }
5810         ++idx;
5811     }
5812     return ys;
5813 }
5814 
5815 // API search type: drop_idx : (Int, [a]) -> [a]
5816 // fwd bind count: 1
5817 // Remove the element at a specific index from a sequence.
5818 // drop_idx(2, [1,2,3,4,5,6,7]) == [1,2,4,5,6,7]
5819 template <typename Container>
drop_idx(std::size_t idx,const Container & xs)5820 Container drop_idx(std::size_t idx, const Container& xs)
5821 {
5822     return drop_by_idx(is_equal_to(idx), xs);
5823 }
5824 
5825 // API search type: justs : [Maybe a] -> [a]
5826 // fwd bind count: 0
5827 // From a Container filled with Maybe<T> the nothings are dropped
5828 // and the values inside the justs are returned in a new container.
5829 template <typename ContainerIn,
5830     typename ContainerOut =
5831         typename internal::same_cont_new_t<ContainerIn,
5832             typename ContainerIn::value_type::type>::type>
justs(const ContainerIn & xs)5833 ContainerOut justs(const ContainerIn& xs)
5834 {
5835     typedef typename ContainerIn::value_type::type T;
5836     auto justsInMaybes = keep_if(is_just<T>, xs);
5837     ContainerOut ys;
5838     internal::prepare_container(ys, fplus::size_of_cont(justsInMaybes));
5839     auto itOut = internal::get_back_inserter<ContainerOut>(ys);
5840     std::transform(std::begin(justsInMaybes), std::end(justsInMaybes),
5841         itOut, unsafe_get_just<T>);
5842     return ys;
5843 }
5844 
5845 // API search type: oks : [Result a b] -> [a]
5846 // fwd bind count: 0
5847 // From a Container filled with Result<Ok, Error> the errors are dropped
5848 // and the values inside the ok are returned in a new container.
5849 template <typename ContainerIn,
5850     typename ContainerOut =
5851         typename internal::same_cont_new_t<ContainerIn,
5852             typename ContainerIn::value_type::ok_t>::type>
oks(const ContainerIn & xs)5853 ContainerOut oks(const ContainerIn& xs)
5854 {
5855     typedef typename ContainerIn::value_type::ok_t Ok;
5856     typedef typename ContainerIn::value_type::error_t Error;
5857     auto oksInResults = keep_if(is_ok<Ok, Error>, xs);
5858     ContainerOut ys;
5859     internal::prepare_container(ys, fplus::size_of_cont(oksInResults));
5860     auto itOut = internal::get_back_inserter<ContainerOut>(ys);
5861     std::transform(std::begin(oksInResults), std::end(oksInResults),
5862         itOut, unsafe_get_ok<Ok, Error>);
5863     return ys;
5864 }
5865 
5866 // API search type: errors : [Result a b] -> [b]
5867 // fwd bind count: 0
5868 // From a Container filled with Result<Ok, Error> the oks are dropped
5869 // and the values inside the errors are returned in a new container.
5870 template <typename ContainerIn,
5871     typename ContainerOut =
5872         typename internal::same_cont_new_t<ContainerIn,
5873             typename ContainerIn::value_type::error_t>::type>
errors(const ContainerIn & xs)5874 ContainerOut errors(const ContainerIn& xs)
5875 {
5876     typedef typename ContainerIn::value_type::ok_t Ok;
5877     typedef typename ContainerIn::value_type::error_t Error;
5878     auto errorsInResults = keep_if(is_error<Ok, Error>, xs);
5879     ContainerOut ys;
5880     internal::prepare_container(ys, fplus::size_of_cont(errorsInResults));
5881     auto itOut = internal::get_back_inserter<ContainerOut>(ys);
5882     std::transform(std::begin(errorsInResults), std::end(errorsInResults),
5883         itOut, unsafe_get_error<Ok, Error>);
5884     return ys;
5885 }
5886 
5887 // API search type: trim_left : (a, [a]) -> [a]
5888 // fwd bind count: 1
5889 // Remove elements from the left as long as they equal x.
5890 // trim_left('_', "___abc__") == "abc__"
5891 // trim_left(0, [0,0,0,5,6,7,8,6,4]) == [5,6,7,8,6,4]
5892 template <typename Container,
5893         typename T = typename Container::value_type>
5894 Container trim_left(const T& x, const Container& xs)
5895 {
5896     return drop_while(is_equal_to(x), xs);
5897 }
5898 
5899 // API search type: trim_token_left : ([a], [a]) -> [a]
5900 // fwd bind count: 1
5901 // Remove elements from the left as long as they match token.
5902 // trim_token_left([0,1,2], [0,1,2,0,1,2,7,5,9]) == [7,5,9]
5903 template <typename Container>
trim_token_left(const Container & token,const Container & xs)5904 Container trim_token_left(const Container& token, const Container& xs)
5905 {
5906     auto result = xs;
5907     while (is_prefix_of(token, result))
5908     {
5909         result = get_segment(size_of_cont(token), size_of_cont(result), result);
5910     }
5911     return result;
5912 }
5913 
5914 // API search type: trim_right_by : ((a -> Bool), [a]) -> [a]
5915 // fwd bind count: 1
5916 // Remove elements from the left as long as p is fulfilled.
5917 // trim_right_by(is_even, [0,2,4,5,6,7,8,6,4]) == [0,2,4,5,6,7]
5918 template <typename Container, typename UnaryPredicate>
5919 Container trim_right_by(UnaryPredicate p, const Container& xs)
5920 {
5921     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
5922     return reverse(drop_while(p, reverse(xs)));
5923 }
5924 
5925 // API search type: trim_right : (a, [a]) -> [a]
5926 // fwd bind count: 1
5927 // Remove elements from the left as long as they equal x.
5928 // trim_right('_', "___abc__") == "___abc"
5929 // trim_right(4, [0,2,4,5,6,7,8,4,4]) == [0,2,4,5,6,7,8]
5930 template <typename Container,
5931         typename T = typename Container::value_type>
5932 Container trim_right(const T& x, const Container& xs)
5933 {
5934     return trim_right_by(is_equal_to(x), xs);
5935 }
5936 
5937 // API search type: trim_token_right : ([a], [a]) -> [a]
5938 // fwd bind count: 1
5939 // Remove elements from the right as long as they match token.
5940 // trim_token_right([0,1,2], [7,5,9,0,1,2,0,1,2]) == [7,5,9]
5941 template <typename Container>
trim_token_right(const Container & token,const Container & xs)5942 Container trim_token_right(const Container& token, const Container& xs)
5943 {
5944     return reverse(trim_token_left(reverse(token), reverse(xs)));
5945 }
5946 
5947 // API search type: trim_by : ((a -> Bool), [a]) -> [a]
5948 // fwd bind count: 1
5949 // Remove elements from the left and right as long as p is fulfilled.
5950 // trim_by(is_even, [0,2,4,5,6,7,8,6,4]) == [5,6,7]
5951 template <typename Container, typename UnaryPredicate>
5952 Container trim_by(UnaryPredicate p, const Container& xs)
5953 {
5954     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
5955     return trim_right_by(p, drop_while(p, xs));
5956 }
5957 
5958 // API search type: trim : (a, [a]) -> [a]
5959 // fwd bind count: 1
5960 // Remove elements from the left and right as long as they equal x.
5961 // trim('_', "___abc__") == "abc"
5962 // trim(0, [0,2,4,5,6,7,8,0,0]) == [2,4,5,6,7,8]
5963 template <typename Container,
5964         typename T = typename Container::value_type>
5965 Container trim(const T& x, const Container& xs)
5966 {
5967     return trim_right(x, trim_left(x, xs));
5968 }
5969 
5970 // API search type: trim_token : ([a], [a]) -> [a]
5971 // fwd bind count: 1
5972 // Remove elements from the left and right as long as they match token.
5973 // trim_token([0,1], [0,1,7,8,9,0,1]) == [7,8,9]
5974 template <typename Container>
trim_token(const Container & token,const Container & xs)5975 Container trim_token(const Container& token, const Container& xs)
5976 {
5977     return trim_token_right(token, trim_token_left(token, xs));
5978 }
5979 
5980 // API search type: adjacent_keep_snd_if : (((a, a) -> Bool), [a]) -> [a]
5981 // fwd bind count: 1
5982 // For each pair of adjacent elements in a source sequence,
5983 // evaluate the specified binary predicate.
5984 // If the predicate evaluates to false,
5985 // the second element of the pair is removed from the result sequence;
5986 // otherwise, it is included.
5987 // The first element in the source sequence is always included.
5988 // Also known as adjacent_filter.
5989 template <typename BinaryPredicate, typename Container>
adjacent_keep_snd_if(BinaryPredicate p,const Container & xs)5990 Container adjacent_keep_snd_if(BinaryPredicate p, const Container& xs)
5991 {
5992     if (is_empty(xs))
5993     {
5994         return {};
5995     }
5996     internal::check_binary_predicate_for_container<BinaryPredicate, Container>();
5997     Container result;
5998     auto it = internal::get_back_inserter<Container>(result);
5999     auto it_in = std::begin(xs);
6000     *it = *it_in;
6001     while (internal::add_to_iterator(it_in) != std::end(xs))
6002     {
6003         if (p(*it_in, *internal::add_to_iterator(it_in)))
6004         {
6005             *it = *internal::add_to_iterator(it_in);
6006         }
6007         internal::advance_iterator(it_in, 1);
6008     }
6009     return result;
6010 }
6011 
6012 // API search type: adjacent_drop_fst_if : (((a, a) -> Bool), [a]) -> [a]
6013 // fwd bind count: 1
6014 // For each pair of adjacent elements in a source sequence,
6015 // evaluate the specified binary predicate.
6016 // If the predicate evaluates to true,
6017 // the first element of the pair is removed from the result sequence;
6018 // otherwise, it is included.
6019 // The last element in the source sequence is always included.
6020 // Also known as adjacent_remove_if.
6021 template <typename BinaryPredicate, typename Container>
adjacent_drop_fst_if(BinaryPredicate p,const Container & xs)6022 Container adjacent_drop_fst_if(BinaryPredicate p, const Container& xs)
6023 {
6024     if (is_empty(xs))
6025     {
6026         return {};
6027     }
6028     internal::check_binary_predicate_for_container<BinaryPredicate, Container>();
6029     Container result;
6030     auto it = internal::get_back_inserter<Container>(result);
6031     auto it_in = std::begin(xs);
6032     while (internal::add_to_iterator(it_in) != std::end(xs))
6033     {
6034         if (!internal::invoke(p, *it_in, *internal::add_to_iterator(it_in)))
6035         {
6036             *it = *it_in;
6037         }
6038         internal::advance_iterator(it_in, 1);
6039     }
6040     *it = *it_in;
6041     return result;
6042 }
6043 
6044 // API search type: adjacent_drop_snd_if : (((a, a) -> Bool), [a]) -> [a]
6045 // fwd bind count: 1
6046 // For each pair of adjacent elements in a source sequence,
6047 // evaluate the specified binary predicate.
6048 // If the predicate evaluates to true,
6049 // the second element of the pair is removed from the result sequence;
6050 // otherwise, it is included.
6051 // The first element in the source sequence is always included.
6052 template <typename BinaryPredicate, typename Container>
adjacent_drop_snd_if(BinaryPredicate p,const Container & xs)6053 Container adjacent_drop_snd_if(BinaryPredicate p, const Container& xs)
6054 {
6055     typedef typename Container::value_type T;
6056     const auto not_p = [&p](const T& x, const T& y) -> bool
6057     {
6058         return !internal::invoke(p, x, y);
6059     };
6060     return adjacent_keep_snd_if(not_p, xs);
6061 }
6062 
6063 // API search type: adjacent_keep_fst_if : (((a, a) -> Bool), [a]) -> [a]
6064 // fwd bind count: 1
6065 // For each pair of adjacent elements in a source sequence,
6066 // evaluate the specified binary predicate.
6067 // If the predicate evaluates to false,
6068 // the first element of the pair is removed from the result sequence;
6069 // otherwise, it is included.
6070 // The last element in the source sequence is always included.
6071 template <typename BinaryPredicate, typename Container>
adjacent_keep_fst_if(BinaryPredicate p,const Container & xs)6072 Container adjacent_keep_fst_if(BinaryPredicate p, const Container& xs)
6073 {
6074     typedef typename Container::value_type T;
6075     const auto not_p = [&p](const T& x, const T& y) -> bool
6076     {
6077         return !internal::invoke(p, x, y);
6078     };
6079     return adjacent_drop_fst_if(not_p, xs);
6080 }
6081 
6082 } // namespace fplus
6083 
6084 
6085 namespace fplus
6086 {
6087 
6088 // API search type: generate : ((() -> a), Int) -> [a]
6089 // Grab values from executing a nullary function
6090 // to generate a sequence of amount values.
6091 // generate(f, 3) == [f(), f(), f()]
6092 // Can for example be used to generate a list of random numbers.
6093 template <typename ContainerOut, typename F>
6094 ContainerOut generate(F f, std::size_t amount)
6095 {
6096     internal::trigger_static_asserts<internal::nullary_function_tag, F>();
6097     ContainerOut ys;
6098     internal::prepare_container(ys, amount);
6099     auto it = internal::get_back_inserter<ContainerOut>(ys);
6100     for (std::size_t i = 0; i < amount; ++i)
6101     {
6102         *it = internal::invoke(f);
6103     }
6104     return ys;
6105 }
6106 
6107 // API search type: generate_by_idx : ((Int -> a), Int) -> [a]
6108 // fwd bind count: 1
6109 // Grab values from executing a unary function with an index
6110 // to generate a sequence of amount values.
6111 // generate_by_idx(f, 3) == [f(0), f(1), f(2)]
6112 template <typename ContainerOut, typename F>
6113 ContainerOut generate_by_idx(F f, std::size_t amount)
6114 {
6115     internal::
6116         trigger_static_asserts<internal::unary_function_tag, F, std::size_t>();
6117 
6118     ContainerOut ys;
6119     internal::prepare_container(ys, amount);
6120     auto it = internal::get_back_inserter<ContainerOut>(ys);
6121     for (std::size_t i = 0; i < amount; ++i)
6122     {
6123         *it = internal::invoke(f, i);
6124     }
6125     return ys;
6126 }
6127 
6128 // API search type: repeat : (Int, [a]) -> [a]
6129 // fwd bind count: 1
6130 // Create a sequence containing xs concatenated n times.
6131 // repeat(3, [1, 2]) == [1, 2, 1, 2, 1, 2]
6132 template <typename Container>
repeat(std::size_t n,const Container & xs)6133 Container repeat(std::size_t n, const Container& xs)
6134 {
6135     std::vector<Container> xss(n, xs);
6136     return concat(xss);
6137 }
6138 
6139 // API search type: infixes : (Int, [a]) -> [[a]]
6140 // fwd bind count: 1
6141 // Return als possible infixed of xs with a given length.
6142 // infixes(3, [1,2,3,4,5,6]) == [[1,2,3], [2,3,4], [3,4,5], [4,5,6]]
6143 // length must be > 0
6144 template <typename ContainerIn,
6145     typename ContainerOut = std::vector<ContainerIn>>
infixes(std::size_t length,const ContainerIn & xs)6146 ContainerOut infixes(std::size_t length, const ContainerIn& xs)
6147 {
6148     assert(length > 0);
6149     static_assert(std::is_convertible<ContainerIn,
6150         typename ContainerOut::value_type>::value,
6151         "ContainerOut can not take values of type ContainerIn as elements.");
6152     ContainerOut result;
6153     if (size_of_cont(xs) < length)
6154         return result;
6155     internal::prepare_container(result, size_of_cont(xs) - length);
6156     auto itOut = internal::get_back_inserter(result);
6157     for (std::size_t idx = 0; idx <= size_of_cont(xs) - length; ++idx)
6158     {
6159         *itOut = get_segment(idx, idx + length, xs);
6160     }
6161     return result;
6162 }
6163 
6164 // API search type: carthesian_product_with_where : (((a, b) -> c), ((a -> b), Bool), [a], [b]) -> [c]
6165 // fwd bind count: 3
6166 // carthesian_product_with_where(make_pair, always(true), "ABC", "XY")
6167 //   == [(A,X),(A,Y),(B,X),(B,Y),(C,X),(C,Y)]
6168 // same as (in Haskell):
6169 //   [ f x y | x <- xs, y <- ys, pred x y ]
6170 // same as (in pseudo SQL):
6171 //   SELECT f(xs.x, ys.y)
6172 //   FROM xs, ys
6173 //   WHERE pred(xs.x, ys.y);
6174 template <typename F, typename Pred, typename Container1, typename Container2>
carthesian_product_with_where(F f,Pred pred,const Container1 & xs,const Container2 & ys)6175 auto carthesian_product_with_where(F f,
6176                                    Pred pred,
6177                                    const Container1& xs,
6178                                    const Container2& ys)
6179 {
6180     using X = typename Container1::value_type;
6181     using Y = typename Container2::value_type;
6182     using FOut = internal::invoke_result_t<F, X, Y>;
6183     using ContainerOut = std::vector<std::decay_t<FOut>>;
6184 
6185     ContainerOut result;
6186     auto itOut = internal::get_back_inserter(result);
6187     for (const auto& x : xs)
6188     {
6189         for (const auto& y : ys)
6190         {
6191             if (internal::invoke(pred, x, y))
6192             {
6193                 itOut = f(x, y);
6194             }
6195         }
6196     }
6197     return result;
6198 }
6199 
6200 // API search type: carthesian_product_with : (((a, b) -> c), [a], [b]) -> [c]
6201 // fwd bind count: 2
6202 // carthesian_product_with(make_pair, "ABC", "XY")
6203 //   == [(A,X),(A,Y),(B,X),(B,Y),(C,X),(C,Y)]
6204 // same as (in Haskell):
6205 //   [ f x y | x <- xs, y <- ys ]
6206 // same as (in pseudo SQL):
6207 //   SELECT f(xs.x, ys.y)
6208 //   FROM xs, ys;
6209 template <typename F, typename Container1, typename Container2>
carthesian_product_with(F f,const Container1 & xs,const Container2 & ys)6210 auto carthesian_product_with(F f, const Container1& xs, const Container2& ys)
6211 {
6212     auto always_true_x_y = [](const auto&, const auto&) { return true; };
6213     return carthesian_product_with_where(f, always_true_x_y, xs, ys);
6214 }
6215 
6216 // API search type: carthesian_product_where : (((a, b) -> Bool), [a], [b]) -> [(a, b)]
6217 // fwd bind count: 2
6218 // carthesian_product_where(always(true), "ABC", "XY")
6219 //   == [(A,X),(A,Y),(B,X),(B,Y),(C,X),(C,Y)]
6220 // same as (in Haskell):
6221 //   [ (x, y) | x <- xs, y <- ys, pred x y ]
6222 // same as (in pseudo SQL):
6223 //   SELECT (xs.x, ys.y)
6224 //   FROM xs, ys
6225 //   WHERE pred(xs.x, ys.y);
6226 template <typename Pred, typename Container1, typename Container2>
carthesian_product_where(Pred pred,const Container1 & xs,const Container2 & ys)6227 auto carthesian_product_where(Pred pred,
6228     const Container1& xs, const Container2& ys)
6229 {
6230     auto make_res_pair = [](const auto& x, const auto& y)
6231     {
6232         return std::make_pair(x, y);
6233     };
6234     return carthesian_product_with_where(make_res_pair, pred, xs, ys);
6235 }
6236 
6237 // API search type: carthesian_product : ([a], [b]) -> [(a, b)]
6238 // fwd bind count: 1
6239 // carthesian_product("ABC", "XY")
6240 //   == [(A,X),(A,Y),(B,X),(B,Y),(C,X),(C,Y)]
6241 // same as (in Haskell):
6242 //   [ (x, y) | x <- xs, y <- ys ]
6243 // same as (in pseudo SQL):
6244 //   SELECT (xs.x, ys.y)
6245 //   FROM xs, ys;
6246 template <typename Container1, typename Container2>
carthesian_product(const Container1 & xs,const Container2 & ys)6247 auto carthesian_product(const Container1& xs, const Container2& ys)
6248 {
6249     auto make_res_pair = [](const auto& x, const auto& y)
6250     {
6251         return std::make_pair(x, y);
6252     };
6253     auto always_true_x_y = [](const auto&, const auto&) { return true; };
6254     return carthesian_product_with_where(
6255         make_res_pair, always_true_x_y, xs, ys);
6256 }
6257 
6258 
6259 namespace internal
6260 {
6261     // productN :: Int -> [a] -> [[a]]
6262     // productN n = foldr go [[]] . replicate n
6263     //     where go elems acc = [x:xs | x <- elems, xs <- acc]
6264     template <typename T>
helper_carthesian_product_n_idxs(std::size_t power,const std::vector<T> & xs)6265     std::vector<std::vector<T>> helper_carthesian_product_n_idxs
6266             (std::size_t power, const std::vector<T>& xs)
6267     {
6268         static_assert(std::is_same<T, std::size_t>::value,
6269             "T must be std::size_t");
6270         typedef std::vector<T> Vec;
6271         typedef std::vector<Vec> VecVec;
6272         if (power == 0)
6273             return VecVec();
6274         auto go = [](const Vec& elems, const VecVec& acc)
6275         {
6276             VecVec result;
6277             for (const T& x : elems)
6278             {
6279                 for (const Vec& tail : acc)
6280                 {
6281                     result.push_back(append(Vec(1, x), tail));
6282                 }
6283             }
6284             return result;
6285         };
6286         return fold_right(go, VecVec(1), replicate(power, xs));
6287     }
6288 }
6289 
6290 // API search type: carthesian_product_n : (Int, [a]) -> [[a]]
6291 // fwd bind count: 1
6292 // Returns the product set with a given power.
6293 // carthesian_product_n(2, "ABCD")
6294 //   == AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
6295 template <typename ContainerIn,
6296     typename T = typename ContainerIn::value_type,
6297     typename ContainerOut = std::vector<ContainerIn>>
carthesian_product_n(std::size_t power,const ContainerIn & xs_in)6298 ContainerOut carthesian_product_n(std::size_t power, const ContainerIn& xs_in)
6299 {
6300     if (power == 0)
6301         return ContainerOut(1);
6302     std::vector<T> xs = convert_container<std::vector<T>>(xs_in);
6303     auto idxs = all_idxs(xs);
6304     auto result_idxss = internal::helper_carthesian_product_n_idxs(power, idxs);
6305     typedef typename ContainerOut::value_type ContainerOutInner;
6306     auto to_result_cont = [&](const std::vector<std::size_t>& indices)
6307     {
6308         return convert_container_and_elems<ContainerOutInner>(
6309             elems_at_idxs(indices, xs));
6310     };
6311     return transform(to_result_cont, result_idxss);
6312 }
6313 
6314 // API search type: permutations : (Int, [a]) -> [[a]]
6315 // fwd bind count: 1
6316 // Generate all possible permutations with a given power.
6317 // permutations(2, "ABCD") == AB AC AD BA BC BD CA CB CD DA DB DC
6318 template <typename ContainerIn,
6319     typename T = typename ContainerIn::value_type,
6320     typename ContainerOut = std::vector<ContainerIn>>
permutations(std::size_t power,const ContainerIn & xs_in)6321 ContainerOut permutations(std::size_t power, const ContainerIn& xs_in)
6322 {
6323     if (power == 0)
6324         return ContainerOut(1);
6325     std::vector<T> xs = convert_container<std::vector<T>>(xs_in);
6326     auto idxs = all_idxs(xs);
6327     typedef std::vector<std::size_t> idx_vec;
6328     auto result_idxss = keep_if(all_unique<idx_vec>,
6329         internal::helper_carthesian_product_n_idxs(power, idxs));
6330     typedef typename ContainerOut::value_type ContainerOutInner;
6331     auto to_result_cont = [&](const std::vector<std::size_t>& indices)
6332     {
6333         return convert_container_and_elems<ContainerOutInner>(
6334             elems_at_idxs(indices, xs));
6335     };
6336     return transform(to_result_cont, result_idxss);
6337 }
6338 
6339 // API search type: combinations : (Int, [a]) -> [[a]]
6340 // fwd bind count: 1
6341 // Generate all possible combinations with a given power.
6342 // combinations(2, "ABCD") == AB AC AD BC BD CD
6343 template <typename ContainerIn,
6344     typename T = typename ContainerIn::value_type,
6345     typename ContainerOut = std::vector<ContainerIn>>
combinations(std::size_t power,const ContainerIn & xs_in)6346 ContainerOut combinations(std::size_t power, const ContainerIn& xs_in)
6347 {
6348     if (power == 0)
6349         return ContainerOut(1);
6350     std::vector<T> xs = convert_container<std::vector<T>>(xs_in);
6351     auto idxs = all_idxs(xs);
6352     typedef std::vector<std::size_t> idx_vec;
6353     auto result_idxss = keep_if(is_strictly_sorted<idx_vec>,
6354         internal::helper_carthesian_product_n_idxs(power, idxs));
6355     typedef typename ContainerOut::value_type ContainerOutInner;
6356     auto to_result_cont = [&](const std::vector<std::size_t>& indices)
6357     {
6358         return convert_container_and_elems<ContainerOutInner>(
6359             elems_at_idxs(indices, xs));
6360     };
6361     return transform(to_result_cont, result_idxss);
6362 }
6363 
6364 // API search type: combinations_with_replacement : (Int, [a]) -> [[a]]
6365 // fwd bind count: 1
6366 // Generate all possible combinations using replacement with a given power.
6367 // combinations_with_replacement(2, "ABCD") == AA AB AC AD BB BC BD CC CD DD
6368 template <typename ContainerIn,
6369     typename T = typename ContainerIn::value_type,
6370     typename ContainerOut = std::vector<ContainerIn>>
combinations_with_replacement(std::size_t power,const ContainerIn & xs_in)6371 ContainerOut combinations_with_replacement(std::size_t power,
6372         const ContainerIn& xs_in)
6373 {
6374     if (power == 0)
6375         return ContainerOut(1);
6376     std::vector<T> xs = convert_container<std::vector<T>>(xs_in);
6377     auto idxs = all_idxs(xs);
6378     typedef std::vector<std::size_t> idx_vec;
6379     auto result_idxss = keep_if(is_sorted<idx_vec>,
6380         internal::helper_carthesian_product_n_idxs(power, idxs));
6381     typedef typename ContainerOut::value_type ContainerOutInner;
6382     auto to_result_cont = [&](const std::vector<std::size_t>& indices)
6383     {
6384         return convert_container_and_elems<ContainerOutInner>(
6385             elems_at_idxs(indices, xs));
6386     };
6387     return transform(to_result_cont, result_idxss);
6388 }
6389 
6390 // API search type: power_set : [a] -> [[a]]
6391 // fwd bind count: 0
6392 // Return the set of all subsets of xs_in,
6393 // including the empty set and xs_in itself.
6394 // power_set("xyz") == ["", "x", "y", "z", "xy", "xz", "yz", "xyz"]
6395 // Also known as subsequences.
6396 template <typename ContainerIn,
6397     typename T = typename ContainerIn::value_type,
6398     typename ContainerOut = std::vector<ContainerIn>>
power_set(const ContainerIn & xs_in)6399 ContainerOut power_set(const ContainerIn& xs_in)
6400 {
6401     return concat(
6402         generate_by_idx<std::vector<ContainerOut>>(
6403             bind_1st_of_2(
6404                 flip(combinations<ContainerIn, T, ContainerOut>),
6405                 xs_in),
6406             size_of_cont(xs_in) + 1));
6407 }
6408 
6409 // API search type: iterate : ((a -> a), Int, a) -> [a]
6410 // fwd bind count: 2
6411 // Repeatedly apply a function (n times) to a value (starting with x)
6412 // and recording the outputs on its way.
6413 // iterate((*2), 5, 3) = [3, 6, 12, 24, 48]
6414 // = [3, f(3), f(f(3)), f(f(f(3))), f(f(f(f(3))))]
6415 template <typename F,
6416     typename T,
6417     typename ContainerOut = std::vector<T>>
iterate(F f,std::size_t size,const T & x)6418 ContainerOut iterate(F f, std::size_t size, const T& x)
6419 {
6420     ContainerOut result;
6421     if (size == 0)
6422         return result;
6423     internal::prepare_container(result, size + 1);
6424     auto it_out = internal::get_back_inserter(result);
6425     T current = x;
6426     *it_out = current;
6427     for (std::size_t i = 1; i < size; ++i)
6428     {
6429         current = internal::invoke(f, current);
6430         *it_out = current;
6431     }
6432     return result;
6433 }
6434 
6435 // API search type: iterate_maybe : ((a -> Maybe a), a) -> [a]
6436 // fwd bind count: 1
6437 // Repeatedly apply a function to a value (starting with x)
6438 // and recording the outputs on its way.
6439 // Stops when the function returns nothing.
6440 // iterate_maybe(next_collats_val, 5) = [5, 16, 8, 4, 2, 1]
6441 template <typename F,
6442     typename T,
6443     typename ContainerOut = std::vector<T>>
iterate_maybe(F f,const T & x)6444 ContainerOut iterate_maybe(F f, const T& x)
6445 {
6446     ContainerOut result;
6447     auto it_out = internal::get_back_inserter(result);
6448     maybe<T> current(x);
6449     while (current.is_just())
6450     {
6451         *it_out = current.unsafe_get_just();
6452         current = internal::invoke(f, current.unsafe_get_just());
6453     }
6454     return result;
6455 }
6456 
6457 // API search type: adjacent_difference_by : [a] -> [a]
6458 // fwd bind count: 1
6459 // Computes the differences between the second
6460 // and the first of each adjacent pair of elements of the sequence
6461 // using a binary function.
6462 // adjacent_difference_by([0,4,1,2,5]) == [0,4,-3,1,3]
6463 template <typename ContainerIn, typename F>
adjacent_difference_by(F f,const ContainerIn & xs)6464 auto adjacent_difference_by(F f, const ContainerIn& xs)
6465 {
6466     using X = typename ContainerIn::value_type;
6467     using TOut = internal::invoke_result_t<F, X, X>;
6468     using ContainerOut = std::vector<std::decay_t<TOut>>;
6469 
6470     ContainerOut result;
6471 
6472     using std::begin;
6473     using std::end;
6474     internal::prepare_container(result, size_of_cont(xs));
6475     std::adjacent_difference(begin(xs), end(xs), back_inserter(result), f);
6476     return result;
6477 }
6478 
6479 // API search type: adjacent_difference : [a] -> [a]
6480 // fwd bind count: 0
6481 // Computes the differences between the second
6482 // and the first of each adjacent pair of elements of the sequence.
6483 // adjacent_difference([0,4,1,2,5]) == [0,4,-3,1,3]
6484 template <typename Container>
adjacent_difference(const Container & xs)6485 Container adjacent_difference(const Container& xs)
6486 {
6487     return adjacent_difference_by(
6488         std::minus<typename Container::value_type>(), xs);
6489 }
6490 
6491 // API search type: rotate_left : [a] -> [a]
6492 // fwd bind count: 0
6493 // Removes the first element and appends it to the back.
6494 // rotate_left("xyz") == "yzx"
6495 template <typename Container>
rotate_left(const Container & xs)6496 Container rotate_left(const Container& xs)
6497 {
6498     if (is_empty(xs))
6499         return xs;
6500     Container ys;
6501     auto size = size_of_cont(xs);
6502     internal::prepare_container(ys, size);
6503     auto it = std::begin(xs);
6504     auto it_out = internal::get_back_inserter(ys);
6505     ++it;
6506     while (it != std::end(xs))
6507     {
6508         *it_out = *it;
6509         ++it;
6510     }
6511     *it_out = xs.front();
6512     return ys;
6513 }
6514 
6515 // API search type: rotate_right : [a] -> [a]
6516 // fwd bind count: 0
6517 // Removes the last element and prepends it to the front.
6518 // rotate_right("xyz") == "zxy"
6519 template <typename Container>
rotate_right(const Container & xs)6520 Container rotate_right(const Container& xs)
6521 {
6522     return reverse(rotate_left(reverse(xs)));
6523 }
6524 
6525 // API search type: rotations_left : [a] -> [[a]]
6526 // fwd bind count: 0
6527 // Returns all possible rotations using rotate_left.
6528 // rotations_left("abcd") == ["abcd", "bcda", "cdab", "dabc"]
6529 template <typename ContainerIn,
6530     typename T = typename ContainerIn::value_type,
6531     typename ContainerOut = std::vector<ContainerIn>>
rotations_left(const ContainerIn & xs_in)6532 ContainerOut rotations_left(const ContainerIn& xs_in)
6533 {
6534     return iterate(rotate_left<ContainerIn>, size_of_cont(xs_in), xs_in);
6535 }
6536 
6537 // API search type: rotations_right : [a] -> [[a]]
6538 // fwd bind count: 0
6539 // Returns all possible rotations using rotate_right.
6540 // rotations_right("abcd") == ["abcd", "dabc", "cdab", "bcda"]
6541 template <typename ContainerIn,
6542     typename T = typename ContainerIn::value_type,
6543     typename ContainerOut = std::vector<ContainerIn>>
rotations_right(const ContainerIn & xs_in)6544 ContainerOut rotations_right(const ContainerIn& xs_in)
6545 {
6546     return iterate(rotate_right<ContainerIn>, size_of_cont(xs_in), xs_in);
6547 }
6548 
6549 // API search type: fill_left : (a, Int, [a]) -> [a]
6550 // fwd bind count: 2
6551 // Right-align a sequence.
6552 // fill_left(0, 6, [1,2,3,4]) == [0,0,1,2,3,4]
6553 // Also known as pad_left.
6554 template <typename Container,
6555         typename T = typename Container::value_type>
6556 Container fill_left(const T& x, std::size_t min_size, const Container& xs)
6557 {
6558     if (min_size <= size_of_cont(xs))
6559         return xs;
6560     return append(replicate<T, Container>(min_size - size_of_cont(xs), x), xs);
6561 }
6562 
6563 // API search type: fill_right : (a, Int, [a]) -> [a]
6564 // fwd bind count: 2
6565 // Left-align a sequence.
6566 // fill_right(0, 6, [1,2,3,4]) == [1,2,3,4,0,0]
6567 template <typename Container,
6568         typename T = typename Container::value_type>
6569 Container fill_right(const T& x, std::size_t min_size, const Container& xs)
6570 {
6571     if (min_size <= size_of_cont(xs))
6572         return xs;
6573     return append(xs, replicate<T, Container>(min_size - size_of_cont(xs), x));
6574 }
6575 
6576 // API search type: inits : [a] -> [[a]]
6577 // fwd bind count: 0
6578 // Generate all possible segments of xs that include the first element.
6579 // inits([0,1,2,3]) == [[],[0],[0,1],[0,1,2],[0,1,2,3]]
6580 template <typename ContainerIn,
6581     typename T = typename ContainerIn::value_type,
6582     typename ContainerOut = std::vector<ContainerIn>>
inits(const ContainerIn & xs)6583 ContainerOut inits(const ContainerIn& xs)
6584 {
6585     ContainerOut result;
6586     std::size_t xs_size = size_of_cont(xs);
6587     internal::prepare_container(result, xs_size + 1);
6588     auto it_out = internal::get_back_inserter(result);
6589     for (std::size_t i = 0; i <= xs_size; ++i)
6590         *it_out = get_segment(0, i, xs);
6591     return result;
6592 }
6593 
6594 // API search type: tails : [a] -> [[a]]
6595 // fwd bind count: 0
6596 // Generate all possible segments of xs that include the last element.
6597 // tails([0,1,2,3]) == [[0,1,2,3],[1,2,3],[2,3],[3],[]]
6598 template <typename ContainerIn,
6599     typename T = typename ContainerIn::value_type,
6600     typename ContainerOut = std::vector<ContainerIn>>
tails(const ContainerIn & xs)6601 ContainerOut tails(const ContainerIn& xs)
6602 {
6603     ContainerOut result;
6604     std::size_t xs_size = size_of_cont(xs);
6605     internal::prepare_container(result, xs_size + 1);
6606     auto it_out = internal::get_back_inserter(result);
6607     for (std::size_t i = 0; i <= xs_size; ++i)
6608         *it_out = get_segment(i, xs_size, xs);
6609     return result;
6610 }
6611 
6612 } // namespace fplus
6613 
6614 //
6615 // numeric.hpp
6616 //
6617 
6618 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
6619 // https://github.com/Dobiasd/FunctionalPlus
6620 // Distributed under the Boost Software License, Version 1.0.
6621 // (See accompanying file LICENSE_1_0.txt or copy at
6622 //  http://www.boost.org/LICENSE_1_0.txt)
6623 
6624 
6625 
6626 //
6627 // pairs.hpp
6628 //
6629 
6630 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
6631 // https://github.com/Dobiasd/FunctionalPlus
6632 // Distributed under the Boost Software License, Version 1.0.
6633 // (See accompanying file LICENSE_1_0.txt or copy at
6634 //  http://www.boost.org/LICENSE_1_0.txt)
6635 
6636 
6637 
6638 //
6639 // internal/asserts/pairs.hpp
6640 //
6641 
6642 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
6643 // https://github.com/Dobiasd/FunctionalPlus
6644 // Distributed under the Boost Software License, Version 1.0.
6645 // (See accompanying file LICENSE_1_0.txt or copy at
6646 //  http://www.boost.org/LICENSE_1_0.txt)
6647 
6648 
6649 
6650 namespace fplus
6651 {
6652 namespace internal
6653 {
6654 struct apply_to_pair_tag
6655 {
6656 };
6657 
6658 struct zip_with_tag
6659 {
6660 };
6661 
6662 struct zip_with_3_tag
6663 {
6664 };
6665 
6666 struct transform_fst_tag
6667 {
6668 };
6669 
6670 struct transform_snd_tag
6671 {
6672 };
6673 
6674 struct inner_product_with_tag
6675 {
6676 };
6677 
6678 template <typename F, typename X, typename Y>
6679 struct function_traits_asserts<apply_to_pair_tag, F, X, Y>
6680 {
6681     static_assert(utils::function_traits<F>::arity == 2,
6682         "Function must take two parameters.");
6683     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
6684     typedef typename utils::function_traits<F>::template arg<1>::type FIn1;
6685     static_assert(std::is_convertible<X, FIn0>::value,
6686         "Function does not take pair.first type as first Parameter.");
6687     static_assert(std::is_convertible<Y, FIn1>::value,
6688         "Function does not take pair.second type as second Parameter.");
6689 };
6690 
6691 template <typename F, typename X, typename Y>
6692 struct function_traits_asserts<zip_with_tag, F, X, Y>
6693 {
6694     static_assert(utils::function_traits<F>::arity == 2,
6695         "Function must take two parameters.");
6696     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
6697     typedef typename utils::function_traits<F>::template arg<1>::type FIn1;
6698     static_assert(std::is_convertible<X, FIn0>::value,
6699         "Function does not take elements from first Container as first Parameter.");
6700     static_assert(std::is_convertible<Y, FIn1>::value,
6701         "Function does not take elements from second Container as second Parameter.");
6702 };
6703 
6704 template <typename F, typename X, typename Y, typename Z>
6705 struct function_traits_asserts<zip_with_3_tag, F, X, Y, Z>
6706 {
6707     static_assert(utils::function_traits<F>::arity == 3,
6708         "Function must take two parameters.");
6709     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
6710     typedef typename utils::function_traits<F>::template arg<1>::type FIn1;
6711     typedef typename utils::function_traits<F>::template arg<2>::type FIn2;
6712     static_assert(std::is_convertible<X, FIn0>::value,
6713         "Function does not take elements from first Container as first Parameter.");
6714     static_assert(std::is_convertible<Y, FIn1>::value,
6715         "Function does not take elements from second Container as second Parameter.");
6716     static_assert(std::is_convertible<Z, FIn2>::value,
6717         "Function does not take elements from third Container as third Parameter.");
6718 };
6719 
6720 template <typename F, typename X>
6721 struct function_traits_asserts<transform_fst_tag, F, X>
6722 {
6723     static_assert(utils::function_traits<F>::arity == 1,
6724         "Function must take one parameter.");
6725     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
6726     static_assert(std::is_convertible<X, FIn0>::value,
6727         "Function does not take pair.first type as first Parameter.");
6728 };
6729 
6730 template <typename F, typename X>
6731 struct function_traits_asserts<transform_snd_tag, F, X>
6732 {
6733     static_assert(utils::function_traits<F>::arity == 1,
6734         "Function must take one parameter.");
6735     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
6736     static_assert(std::is_convertible<X, FIn0>::value,
6737         "Function does not take pair.second type as first Parameter.");
6738 };
6739 
6740 template <typename F, typename X, typename Y>
6741 struct function_traits_asserts<inner_product_with_tag, F, X, Y>
6742 {
6743     static_assert(utils::function_traits<F>::arity == 2,
6744         "Function must take two parameters.");
6745     typedef typename utils::function_traits<F>::template arg<0>::type FIn0;
6746     typedef typename utils::function_traits<F>::template arg<1>::type FIn1;
6747     static_assert(std::is_convertible<X, FIn0>::value,
6748         "Function does not take elements from first Container as first Parameter.");
6749     static_assert(std::is_convertible<Y, FIn1>::value,
6750         "Function does not take elements from second Container as second Parameter.");
6751 };
6752 }
6753 }
6754 
6755 #include <utility>
6756 
6757 namespace fplus
6758 {
6759 // API search type: apply_to_pair : (((a, b) -> c), (a, b)) -> c
6760 // fwd bind count: 1
6761 // Apply binary function to parts of a pair.
6762 template <typename F, typename FIn0, typename FIn1>
apply_to_pair(F f,const std::pair<FIn0,FIn1> & p)6763 auto apply_to_pair(F f, const std::pair<FIn0, FIn1>& p)
6764 {
6765     internal::trigger_static_asserts<internal::apply_to_pair_tag, F, FIn0, FIn1>();
6766     return internal::invoke(f, p.first, p.second);
6767 }
6768 
6769 // API search type: zip_with : (((a, b) -> c), [a], [b]) -> [c]
6770 // fwd bind count: 2
6771 // Zip two sequences using a binary function.
6772 // zip_with((+), [1, 2, 3], [5, 6]) == [1+5, 2+6] == [6, 8]
6773 template <typename ContainerIn1,
6774           typename ContainerIn2,
6775           typename F,
6776           typename X = typename ContainerIn1::value_type,
6777           typename Y = typename ContainerIn2::value_type,
6778           typename TOut = std::decay_t<internal::invoke_result_t<F, X, Y>>,
6779           typename ContainerOut = std::vector<TOut>>
zip_with(F f,const ContainerIn1 & xs,const ContainerIn2 & ys)6780 ContainerOut zip_with(F f, const ContainerIn1& xs, const ContainerIn2& ys)
6781 {
6782     internal::trigger_static_asserts<internal::zip_with_tag, F, X, Y>();
6783     ContainerOut result;
6784     std::size_t resultSize = std::min(size_of_cont(xs), size_of_cont(ys));
6785     internal::prepare_container(result, resultSize);
6786     auto itResult = internal::get_back_inserter(result);
6787     auto itXs = std::begin(xs);
6788     auto itYs = std::begin(ys);
6789     for (std::size_t i = 0; i < resultSize; ++i)
6790     {
6791         *itResult = internal::invoke(f, *itXs, *itYs);
6792         ++itXs;
6793         ++itYs;
6794     }
6795   return result;
6796 }
6797 
6798 // API search type: zip_with_3 : (((a, b, c) -> d), [a], [b], [c]) -> [c]
6799 // fwd bind count: 3
6800 // Zip three sequences using a ternary function.
6801 // zip_with_3((+), [1, 2, 3], [5, 6], [1, 1]) == [7, 9]
6802 template <
6803     typename ContainerIn1,
6804     typename ContainerIn2,
6805     typename ContainerIn3,
6806     typename F,
6807     typename X = typename ContainerIn1::value_type,
6808     typename Y = typename ContainerIn2::value_type,
6809     typename Z = typename ContainerIn3::value_type,
6810     typename TOut = std::decay_t<internal::invoke_result_t<F, X, Y, Z>>,
6811     typename ContainerOut = typename std::vector<TOut>>
zip_with_3(F f,const ContainerIn1 & xs,const ContainerIn2 & ys,const ContainerIn3 & zs)6812 ContainerOut zip_with_3(F f,
6813                         const ContainerIn1& xs,
6814                         const ContainerIn2& ys,
6815                         const ContainerIn3& zs)
6816 {
6817     internal::trigger_static_asserts<internal::zip_with_3_tag, F, X, Y, Z>();
6818     static_assert(std::is_same<
6819         typename internal::same_cont_new_t<ContainerIn1, void>::type,
6820         typename internal::same_cont_new_t<ContainerIn2, void>::type>::value,
6821         "All three Containers must be of same outer type.");
6822     static_assert(std::is_same<
6823         typename internal::same_cont_new_t<ContainerIn2, void>::type,
6824         typename internal::same_cont_new_t<ContainerIn3, void>::type>::value,
6825         "All three Containers must be of same outer type.");
6826     ContainerOut result;
6827     std::size_t resultSize = std::min(size_of_cont(xs), size_of_cont(ys));
6828     internal::prepare_container(result, resultSize);
6829     auto itResult = internal::get_back_inserter(result);
6830     auto itXs = std::begin(xs);
6831     auto itYs = std::begin(ys);
6832     auto itZs = std::begin(zs);
6833     for (std::size_t i = 0; i < resultSize; ++i)
6834     {
6835         *itResult = internal::invoke(f, *itXs, *itYs, *itZs);
6836         ++itXs;
6837         ++itYs;
6838         ++itZs;
6839     }
6840     return result;
6841 }
6842 
6843 // API search type: zip_with_defaults : (((a, b) -> c), a, b, [a], [b]) -> [c]
6844 // fwd bind count: 4
6845 // Zip two sequences and using a binary function
6846 // and extrapolate the shorter sequence with a default value.
6847 // zip_with_defaults((+), 6, 7, [1,2,3], [1,2]) == [2,4,10]
6848 // zip_with_defaults((+), 6, 7, [1,2], [1,2,3]) == [2,4,9]
6849 template <
6850     typename ContainerIn1,
6851     typename ContainerIn2,
6852     typename F,
6853     typename X = typename ContainerIn1::value_type,
6854     typename Y = typename ContainerIn2::value_type>
zip_with_defaults(F f,const X & default_x,const Y & default_y,const ContainerIn1 & xs,const ContainerIn2 & ys)6855 auto zip_with_defaults(F f,
6856     const X& default_x,
6857     const Y& default_y,
6858     const ContainerIn1& xs,
6859     const ContainerIn2& ys)
6860 {
6861     internal::trigger_static_asserts<internal::zip_with_tag, F, X, Y>();
6862     const auto size_xs = size_of_cont(xs);
6863     const auto size_ys = size_of_cont(ys);
6864     if (size_xs < size_ys)
6865     {
6866         const auto extended_xs = append(
6867             xs,
6868             replicate<X, ContainerIn1>(size_ys - size_xs, default_x));
6869         return zip_with(f, extended_xs, ys);
6870     }
6871     else if (size_xs > size_ys)
6872     {
6873         const auto extended_ys = append(
6874             ys,
6875             replicate<Y, ContainerIn2>(size_xs - size_ys, default_y));
6876         return zip_with(f, xs, extended_ys);
6877     }
6878     return zip_with(f, xs, ys);
6879 }
6880 
6881 // API search type: zip : ([a], [b]) -> [(a, b)]
6882 // fwd bind count: 1
6883 // Combine two sequences to one sequence of pairs.
6884 // zip([1, 2, 3], [5, 6]) == [(1, 5), (2, 6)]
6885 template <typename ContainerIn1, typename ContainerIn2,
6886     typename X = typename ContainerIn1::value_type,
6887     typename Y = typename ContainerIn2::value_type>
zip(const ContainerIn1 & xs,const ContainerIn2 & ys)6888 auto zip(const ContainerIn1& xs, const ContainerIn2& ys)
6889 {
6890     auto MakePair = [](const X& x, const Y& y)
6891         { return std::make_pair(x, y); };
6892     return zip_with(MakePair, xs, ys);
6893 }
6894 
6895 // API search type: zip_repeat : ([a], [b]) -> [(a, b)]
6896 // fwd bind count: 1
6897 // Similar to zip but repeats the shorter sequence
6898 // to align with the longer sequence.
6899 // zip([1, 2, 3, 4], [5, 6]) == [(1, 5), (2, 6), (3, 5), (4, 6)]
6900 template <typename ContainerIn1, typename ContainerIn2>
zip_repeat(const ContainerIn1 & xs,const ContainerIn2 & ys)6901 auto zip_repeat(const ContainerIn1& xs, const ContainerIn2& ys)
6902 {
6903     auto nx = xs.size();
6904     auto ny = ys.size();
6905     auto qx = ny/nx + (ny % nx ?  1 : 0);
6906     auto qy = nx/ny + (nx % ny ?  1 : 0);
6907     return zip(qx > 1 ? repeat(qx, xs) : xs,
6908                qy > 1 ? repeat(qy, ys) : ys);
6909 }
6910 
6911 // API search type: unzip : [(a, b)] -> ([a], [b])
6912 // fwd bind count: 0
6913 // Split a sequence of pairs into two sequences.
6914 // unzip([(1, 5), (2, 6)]) == ([1, 2], [5, 6])
6915 template <typename ContainerIn,
6916     typename TIn = typename ContainerIn::value_type,
6917     typename X = typename TIn::first_type,
6918     typename Y = typename TIn::second_type,
6919     typename ContainerOutX = typename internal::same_cont_new_t<ContainerIn, X>::type,
6920     typename ContainerOutY = typename internal::same_cont_new_t<ContainerIn, Y>::type>
unzip(const ContainerIn & pairs)6921 std::pair<ContainerOutX, ContainerOutY> unzip(const ContainerIn& pairs)
6922 {
6923     ContainerOutX firsts;
6924     ContainerOutY seconds;
6925     internal::prepare_container(firsts, size_of_cont(pairs));
6926     internal::prepare_container(seconds, size_of_cont(pairs));
6927     auto itFirsts = internal::get_back_inserter(firsts);
6928     auto itSeconds = internal::get_back_inserter(seconds);
6929     for (const auto& pair : pairs)
6930     {
6931         *itFirsts = pair.first;
6932         *itSeconds = pair.second;
6933     }
6934     return std::make_pair(firsts, seconds);
6935 }
6936 
6937 // API search type: fst : ((a, b)) -> a
6938 // fwd bind count: 0
6939 // Return the first element of a pair.
6940 // fst((0, 1)) == 0
6941 template <typename X, typename Y>
6942 X fst(const std::pair<X, Y>& pair)
6943 {
6944     return pair.first;
6945 }
6946 
6947 // API search type: snd : ((a, b)) -> b
6948 // fwd bind count: 0
6949 // Return the second element of a pair.
6950 // snd((0, 1)) == 1
6951 template <typename X, typename Y>
snd(const std::pair<X,Y> & pair)6952 Y snd(const std::pair<X, Y>& pair)
6953 {
6954     return pair.second;
6955 }
6956 
6957 // API search type: transform_fst : ((a -> c), (a, b)) -> (c, b)
6958 // fwd bind count: 1
6959 // Apply a function to the first element of a pair.
6960 // transform_fst(square, (4, 5)) == (16, 5)
6961 template <typename X, typename Y, typename F,
6962     typename ResultFirst = std::decay_t<internal::invoke_result_t<F, X>>>
transform_fst(F f,const std::pair<X,Y> & pair)6963 std::pair<ResultFirst, Y> transform_fst(F f, const std::pair<X, Y>& pair)
6964 {
6965     internal::trigger_static_asserts<internal::transform_fst_tag, F, X>();
6966     return std::make_pair(internal::invoke(f, pair.first), pair.second);
6967 }
6968 
6969 // API search type: transform_snd : ((b -> c), (a, b)) -> (a, c)
6970 // fwd bind count: 1
6971 // Apply a function to the second element of a pair.
6972 // transform_snd(square, (4, 5)) == (4, 25)
6973 template <typename X, typename Y, typename F,
6974     typename ResultSecond = std::decay_t<internal::invoke_result_t<F, Y>>>
transform_snd(F f,const std::pair<X,Y> & pair)6975 std::pair<X, ResultSecond> transform_snd(F f, const std::pair<X, Y>& pair)
6976 {
6977     internal::trigger_static_asserts<internal::transform_snd_tag, F, Y>();
6978     return std::make_pair(pair.first, internal::invoke(f, pair.second));
6979 }
6980 
6981 // API search type: transform_pair : ((a -> c), (b -> d), (a, b)) -> (c, d)
6982 // fwd bind count: 2
6983 // Apply functions the both parts of a pair.
6984 // transform_pair(square, square, (4, 5)) == (16, 25)
6985 template <
6986     typename X,
6987     typename Y,
6988     typename F,
6989     typename G,
6990     typename ResultFirst = std::decay_t<internal::invoke_result_t<F, X>>,
6991     typename ResultSecond = std::decay_t<internal::invoke_result_t<G, Y>>>
transform_pair(F f,G g,const std::pair<X,Y> & pair)6992 std::pair<ResultFirst, ResultSecond> transform_pair(F f,
6993                                                     G g,
6994                                                     const std::pair<X, Y>& pair)
6995 {
6996     internal::trigger_static_asserts<internal::transform_fst_tag, F, X>();
6997     internal::trigger_static_asserts<internal::transform_snd_tag, G, Y>();
6998     return std::make_pair(internal::invoke(f, pair.first),
6999                           internal::invoke(g, pair.second));
7000 }
7001 
7002 // API search type: swap_pair_elems : (a, b) -> (b, a)
7003 // fwd bind count: 0
7004 // Swap the first and the second element of a pair.
7005 // swap_pair_elems((3,4)) == (4,3)
7006 template <typename X, typename Y>
swap_pair_elems(const std::pair<X,Y> & pair)7007 std::pair<Y, X> swap_pair_elems(const std::pair<X, Y>& pair)
7008 {
7009     return std::make_pair(pair.second, pair.first);
7010 }
7011 
7012 // API search type: swap_pairs_elems : [(a, b)] -> [(b, a)]
7013 // fwd bind count: 0
7014 // Swap the first and the second element of every pair in a sequence.
7015 // swap_pairs_elems([(1,2), (3,4)]) == [(2,1), (4,3)]
7016 template <typename ContainerIn,
7017     typename X = typename ContainerIn::value_type::first_type,
7018     typename Y = typename ContainerIn::value_type::second_type>
swap_pairs_elems(const ContainerIn & xs)7019 auto swap_pairs_elems(const ContainerIn& xs)
7020 {
7021     return fplus::transform(swap_pair_elems<X, Y>, xs);
7022 }
7023 
7024 // API search type: adjacent_pairs : [a] -> [(a, a)]
7025 // fwd bind count: 0
7026 // Split a sequence into pairs of elements.
7027 // adjacent_pairs([0,1,2,3,4]) == [(0,1), (2,3)]
7028 // Also known as zip_with_next.
7029 template <typename Container,
7030     typename ContainerOut =
7031         typename internal::same_cont_new_t<Container,
7032             std::pair<
7033                 typename Container::value_type,
7034                     typename Container::value_type>>::type>
adjacent_pairs(const Container & xs)7035 ContainerOut adjacent_pairs(const Container& xs)
7036 {
7037     typedef typename Container::value_type T;
7038     static_assert(std::is_convertible<
7039             std::pair<T, T>,
7040             typename ContainerOut::value_type>::value,
7041         "ContainerOut can not store pairs of elements from ContainerIn.");
7042     ContainerOut result;
7043     if (size_of_cont(xs) < 2)
7044         return result;
7045     const std::size_t out_size = size_of_cont(xs) / 2;
7046     internal::prepare_container(result, out_size);
7047     auto itOut = internal::get_back_inserter(result);
7048     auto it1 = std::begin(xs);
7049     auto it2 = it1;
7050     internal::advance_iterator(it2, 1);
7051     const auto it_source_end =
7052         internal::add_to_iterator(std::begin(xs), out_size + out_size);
7053     for (;;)
7054     {
7055         *itOut = std::make_pair(*it1, *it2);
7056         internal::advance_iterator(it1, 2);
7057         if (it1 == it_source_end)
7058             break;
7059         internal::advance_iterator(it2, 2);
7060     }
7061     return result;
7062 }
7063 
7064 // API search type: overlapping_pairs : [a] -> [(a, a)]
7065 // fwd bind count: 0
7066 // Zip a sequence with itself shifted one element.
7067 // overlapping_pairs([0,1,2,3]) == [(0,1),(1,2),(2,3)]
7068 template <typename Container,
7069     typename ContainerOut =
7070         typename internal::same_cont_new_t<Container,
7071             std::pair<
7072                 typename Container::value_type,
7073                     typename Container::value_type>, -1>::type>
overlapping_pairs(const Container & xs)7074 ContainerOut overlapping_pairs(const Container& xs)
7075 {
7076     typedef typename Container::value_type T;
7077     static_assert(std::is_convertible<
7078             std::pair<T, T>,
7079             typename ContainerOut::value_type>::value,
7080         "ContainerOut can not store pairs of elements from ContainerIn.");
7081     ContainerOut result;
7082     if (size_of_cont(xs) < 2)
7083         return result;
7084     internal::prepare_container(result, size_of_cont(xs) - 1);
7085     auto itOut = internal::get_back_inserter(result);
7086     auto it1 = std::begin(xs);
7087     auto it2 = it1;
7088     internal::advance_iterator(it2, 1);
7089     for (; it2 != std::end(xs); ++it1, ++it2)
7090     {
7091         *itOut = std::make_pair(*it1, *it2);
7092     }
7093     return result;
7094 }
7095 
7096 // API search type: overlapping_pairs_cyclic : [a] -> [(a, a)]
7097 // fwd bind count: 0
7098 // Zip a sequence with itself shifted one element,
7099 // finally zipping the last element with the first one.
7100 // overlapping_pairs_cyclic([0,1,2,3]) == [(0,1),(1,2),(2,3),(3,0)]
7101 template <typename Container,
7102     typename ContainerOut =
7103         typename internal::same_cont_new_t<Container,
7104             std::pair<
7105                 typename Container::value_type,
7106                     typename Container::value_type>, 0>::type>
overlapping_pairs_cyclic(const Container & xs)7107 ContainerOut overlapping_pairs_cyclic(const Container& xs)
7108 {
7109     typedef typename Container::value_type T;
7110     static_assert(std::is_convertible<
7111             std::pair<T, T>,
7112             typename ContainerOut::value_type>::value,
7113         "ContainerOut can not store pairs of elements from ContainerIn.");
7114     ContainerOut result;
7115     if (size_of_cont(xs) < 2)
7116         return result;
7117     internal::prepare_container(result, size_of_cont(xs));
7118     auto itOut = internal::get_back_inserter(result);
7119     auto it1 = std::begin(xs);
7120     auto it2 = it1;
7121     internal::advance_iterator(it2, 1);
7122     for (; it2 != std::end(xs); ++it1, ++it2)
7123     {
7124         *itOut = std::make_pair(*it1, *it2);
7125     }
7126     *itOut = std::make_pair(*it1, xs.front());
7127     return result;
7128 }
7129 
7130 // API search type: enumerate : [a] -> [(Int, a)]
7131 // fwd bind count: 0
7132 // Attach its index to every element of a sequence.
7133 // enumerate([6,4,7,6]) == [(0, 6), (1, 4), (2, 7), (3, 6)]
7134 template <typename Container>
enumerate(const Container & xs)7135 auto enumerate(const Container& xs)
7136 {
7137     return zip(all_idxs(xs), xs);
7138 }
7139 
7140 // API search type: inner_product_with : (((a, a) -> b), ((b, b) -> b), b, [a], [a]) -> b
7141 // fwd bind count: 4
7142 // Calculate the inner product of two sequences using custom operations.
7143 // inner_product_with((+), (*), [1, 2, 3], [4, 5, 6]) == [32]
7144 template <
7145     typename ContainerIn1,
7146     typename ContainerIn2,
7147     typename OP1,
7148     typename OP2,
7149     typename Acc,
7150     typename X = typename ContainerIn1::value_type,
7151     typename Y = typename ContainerIn2::value_type,
7152     typename OP2Out = internal::invoke_result_t<OP2, X, Y>>
inner_product_with(OP1 op1,OP2 op2,const Acc & value,const ContainerIn1 & xs,const ContainerIn2 & ys)7153 auto inner_product_with(OP1 op1,
7154                         OP2 op2,
7155                         const Acc& value,
7156                         const ContainerIn1& xs,
7157                         const ContainerIn2& ys)
7158 {
7159     internal::trigger_static_asserts<internal::inner_product_with_tag, OP2, X, Y>();
7160     internal::trigger_static_asserts<internal::inner_product_with_tag, OP1, Acc, OP2Out>();
7161     assert(size_of_cont(xs) == size_of_cont(ys));
7162     return std::inner_product(
7163         std::begin(xs), std::end(xs), std::begin(ys), value, op1, op2);
7164 }
7165 
7166 // API search type: inner_product : (a, [a], [a]) -> a
7167 // fwd bind count: 2
7168 // Calculate the inner product of two sequences.
7169 // inner_product([1, 2, 3], [4, 5, 6]) == [32]
7170 template <typename ContainerIn1, typename ContainerIn2,
7171     typename Z>
inner_product(const Z & value,const ContainerIn1 & xs,const ContainerIn2 & ys)7172 Z inner_product(const Z& value,
7173         const ContainerIn1& xs, const ContainerIn2& ys)
7174 {
7175     assert(size_of_cont(xs) == size_of_cont(ys));
7176 
7177     return std::inner_product(
7178         std::begin(xs), std::end(xs), std::begin(ys), value);
7179 }
7180 
7181 // API search type: first_mismatch_idx_by : (((a, b) -> Bool), [a], [b]) -> Maybe Int
7182 // fwd bind count: 2
7183 // Find the first index at which the two sequences differ
7184 // using a binary predicate.
7185 // first_mismatch_idx_by((==), [1, 2, 3], [1, 4, 3]) == Just 1
7186 // first_mismatch_idx_by((==), [1, 2, 3], [1, 4]) == Just 1
7187 // first_mismatch_idx_by((==), [1, 2, 3], [1, 2]) == Nothing
7188 // first_mismatch_idx_by((==), [], [1, 2]) == Nothing
7189 template <typename ContainerIn1, typename ContainerIn2,
7190     typename BinaryPredicate>
first_mismatch_idx_by(BinaryPredicate p,const ContainerIn1 & xs,const ContainerIn2 & ys)7191 maybe<std::size_t> first_mismatch_idx_by(BinaryPredicate p,
7192     const ContainerIn1& xs, const ContainerIn2& ys)
7193 {
7194     auto itXs = std::begin(xs);
7195     auto itYs = std::begin(ys);
7196     std::size_t minSize = std::min(size_of_cont(xs), size_of_cont(ys));
7197     for (std::size_t i = 0; i < minSize; ++i)
7198     {
7199         if (!internal::invoke(p, *itXs, *itYs))
7200         {
7201             return just(i);
7202         }
7203         ++itXs;
7204         ++itYs;
7205     }
7206     return nothing<std::size_t>();
7207 }
7208 
7209 // API search type: first_mismatch_by : (((a, b) -> Bool), [a], [b]) -> Maybe (a, b)
7210 // fwd bind count: 2
7211 // Find the first pair of elements differing in the two sequences
7212 // using a binary predicate.
7213 // first_mismatch_by((==), [1, 2, 3], [1, 4, 3]) == Just (2, 4)
7214 // first_mismatch_by((==), [1, 2, 3], [1, 4]) == Just (2, 4)
7215 // first_mismatch_by((==), [1, 2, 3], [1, 2]) == Nothing
7216 // first_mismatch_by((==), [], [1, 2]) == Nothing
7217 template <typename ContainerIn1, typename ContainerIn2,
7218     typename BinaryPredicate,
7219     typename X = typename ContainerIn1::value_type,
7220     typename Y = typename ContainerIn2::value_type,
7221     typename TOut = std::pair<X, Y>>
first_mismatch_by(BinaryPredicate p,const ContainerIn1 & xs,const ContainerIn2 & ys)7222 maybe<TOut> first_mismatch_by(BinaryPredicate p,
7223     const ContainerIn1& xs, const ContainerIn2& ys)
7224 {
7225     const auto maybe_idx = first_mismatch_idx_by(p, xs, ys);
7226     if (is_nothing(maybe_idx))
7227     {
7228         return nothing<TOut>();
7229     }
7230     else
7231     {
7232         const auto idx = maybe_idx.unsafe_get_just();
7233         return just(std::make_pair(
7234             elem_at_idx(idx, xs),
7235             elem_at_idx(idx, ys)));
7236     }
7237 }
7238 
7239 // API search type: first_mismatch_idx_on : ((a -> b), [a], [a]) -> Maybe Int
7240 // fwd bind count: 2
7241 // Find the first index of elements differing in the two sequences
7242 // using a transformer.
7243 // first_mismatch_idx_on((mod 2), [1, 2, 3], [3, 5, 3]) == 1
7244 // first_mismatch_idx_on((mod 2), [1, 2, 3], [1, 5]) == 1
7245 // first_mismatch_idx_on((mod 2), [1, 2, 3], [1, 6]) == Nothing
7246 // first_mismatch_idx_on((mod 2), [], [1, 2]) == Nothing
7247 template <typename ContainerIn1, typename ContainerIn2,
7248     typename F,
7249     typename X = typename ContainerIn1::value_type,
7250     typename Y = typename ContainerIn2::value_type,
7251     typename TOut = std::pair<X, Y>>
first_mismatch_idx_on(F f,const ContainerIn1 & xs,const ContainerIn2 & ys)7252 maybe<std::size_t> first_mismatch_idx_on(F f,
7253     const ContainerIn1& xs, const ContainerIn2& ys)
7254 {
7255     static_assert(std::is_same<X, Y>::value,
7256         "Both containers must have the same element type.");
7257     return first_mismatch_idx_by(is_equal_by(f), xs, ys);
7258 }
7259 
7260 // API search type: first_mismatch_on : ((a -> b), [a], [a]) -> Maybe (a, a)
7261 // fwd bind count: 2
7262 // Find the first pair of elements differing in the two sequences
7263 // using a transformer.
7264 // first_mismatch_on((mod 2), [1, 2, 3], [3, 5, 3]) == Just (2, 5)
7265 // first_mismatch_on((mod 2), [1, 2, 3], [1, 5]) == Just (2, 5)
7266 // first_mismatch_on((mod 2), [1, 2, 3], [1, 6]) == Nothing
7267 // first_mismatch_on((mod 2), [], [1, 2]) == Nothing
7268 template <typename ContainerIn1, typename ContainerIn2,
7269     typename F,
7270     typename X = typename ContainerIn1::value_type,
7271     typename Y = typename ContainerIn2::value_type,
7272     typename TOut = std::pair<X, Y>>
first_mismatch_on(F f,const ContainerIn1 & xs,const ContainerIn2 & ys)7273 maybe<TOut> first_mismatch_on(F f,
7274     const ContainerIn1& xs, const ContainerIn2& ys)
7275 {
7276     static_assert(std::is_same<X, Y>::value,
7277         "Both containers must have the same element type.");
7278     return first_mismatch_by(is_equal_by(f), xs, ys);
7279 }
7280 
7281 // API search type: first_mismatch_idx : ([a], [a]) -> Maybe Int
7282 // fwd bind count: 2
7283 // Find the first index of elements differing in the two sequences.
7284 // first_mismatch_idx((==), [1, 2, 3], [1, 4, 3]) == 1
7285 // first_mismatch_idx((==), [1, 2, 3], [1, 4]) == 1
7286 // first_mismatch_idx((==), [1, 2, 3], [1, 2]) == Nothing
7287 // first_mismatch_idx((==), [], [1, 2]) == Nothing
7288 template <typename ContainerIn1, typename ContainerIn2,
7289     typename X = typename ContainerIn1::value_type,
7290     typename Y = typename ContainerIn2::value_type>
first_mismatch_idx(const ContainerIn1 & xs,const ContainerIn2 & ys)7291 maybe<std::size_t> first_mismatch_idx(
7292     const ContainerIn1& xs, const ContainerIn2& ys)
7293 {
7294     static_assert(std::is_same<X, Y>::value,
7295         "Both containers must have the same element type.");
7296     return first_mismatch_idx_by(std::equal_to<X>(), xs, ys);
7297 }
7298 
7299 // API search type: first_mismatch : ([a], [a]) -> Maybe (a, a)
7300 // fwd bind count: 2
7301 // Find the first pair of elements differing in the two sequences
7302 // first_mismatch((==), [1, 2, 3], [1, 4, 3]) == Just (2, 4)
7303 // first_mismatch((==), [1, 2, 3], [1, 4]) == Just (2, 4)
7304 // first_mismatch((==), [1, 2, 3], [1, 2]) == Nothing
7305 // first_mismatch((==), [], [1, 2]) == Nothing
7306 template <typename ContainerIn1, typename ContainerIn2,
7307     typename X = typename ContainerIn1::value_type,
7308     typename Y = typename ContainerIn2::value_type,
7309     typename TOut = std::pair<X, Y>>
first_mismatch(const ContainerIn1 & xs,const ContainerIn2 & ys)7310 maybe<TOut> first_mismatch(const ContainerIn1& xs, const ContainerIn2& ys)
7311 {
7312     static_assert(std::is_same<X, Y>::value,
7313         "Both containers must have the same element type.");
7314     return first_mismatch_by(std::equal_to<X>(), xs, ys);
7315 }
7316 
7317 // API search type: first_match_idx_by : (((a, b) -> Bool), [a], [b]) -> Maybe Int
7318 // fwd bind count: 2
7319 // Find the first index at which the two sequences equal
7320 // using a binary predicate.
7321 // first_match_idx_by((==), [1, 2, 3], [3, 2, 3]) == Just 1
7322 // first_match_idx_by((==), [], [1, 2]) == Nothing
7323 template <typename ContainerIn1, typename ContainerIn2,
7324     typename F,
7325     typename X = typename ContainerIn1::value_type,
7326     typename Y = typename ContainerIn2::value_type>
first_match_idx_by(F f,const ContainerIn1 & xs,const ContainerIn2 & ys)7327 maybe<std::size_t> first_match_idx_by(F f,
7328     const ContainerIn1& xs, const ContainerIn2& ys)
7329 {
7330     auto itXs = std::begin(xs);
7331     auto itYs = std::begin(ys);
7332     std::size_t minSize = std::min(size_of_cont(xs), size_of_cont(ys));
7333     for (std::size_t i = 0; i < minSize; ++i)
7334     {
7335         if (internal::invoke(f, *itXs, *itYs))
7336         {
7337             return just(i);
7338         }
7339         ++itXs;
7340         ++itYs;
7341     }
7342     return nothing<std::size_t>();
7343 }
7344 
7345 // API search type: first_match_by : (((a, b) -> Bool), [a], [b]) -> Maybe (a, b)
7346 // fwd bind count: 2
7347 // Find the first pair of equal elements in the two sequences
7348 // using a binary predicate.
7349 // first_match_by((==), [1, 2, 3], [3, 2, 3]) == Just (2, 2)
7350 // first_match_by((==), [], [1, 2]) == Nothing
7351 template <typename ContainerIn1, typename ContainerIn2,
7352     typename F,
7353     typename X = typename ContainerIn1::value_type,
7354     typename Y = typename ContainerIn2::value_type,
7355     typename TOut = std::pair<X, Y>>
first_match_by(F f,const ContainerIn1 & xs,const ContainerIn2 & ys)7356 maybe<TOut> first_match_by(F f, const ContainerIn1& xs, const ContainerIn2& ys)
7357 {
7358     const auto maybe_idx = first_match_idx_by(f, xs, ys);
7359     if (is_nothing(maybe_idx))
7360     {
7361         return nothing<TOut>();
7362     }
7363     else
7364     {
7365         const auto idx = maybe_idx.unsafe_get_just();
7366         return just(std::make_pair(
7367             elem_at_idx(idx, xs),
7368             elem_at_idx(idx, ys)));
7369     }
7370 }
7371 
7372 // API search type: first_match_idx_on : ((a -> b), [a], [a]) -> Maybe Int
7373 // fwd bind count: 2
7374 // Find the first index of equal elements in the two sequences
7375 // using a transformer.
7376 // first_match_idx_on((mod 2), [1, 2, 3], [2, 4, 3]) == 1
7377 // first_match_idx_on((mod 2), [], [1, 2]) == Nothing
7378 template <typename ContainerIn1, typename ContainerIn2,
7379     typename F,
7380     typename X = typename ContainerIn1::value_type,
7381     typename Y = typename ContainerIn2::value_type>
first_match_idx_on(F f,const ContainerIn1 & xs,const ContainerIn2 & ys)7382 maybe<std::size_t> first_match_idx_on(F f,
7383     const ContainerIn1& xs, const ContainerIn2& ys)
7384 {
7385     static_assert(std::is_same<X, Y>::value,
7386         "Both containers must have the same element type.");
7387     return first_match_idx_by(is_equal_by(f), xs, ys);
7388 }
7389 
7390 // API search type: first_match_on : ((a -> b), [a], [a]) -> Maybe (a, a)
7391 // fwd bind count: 2
7392 // Find the first pair of equal elements in the two sequences
7393 // using a transformer.
7394 // first_match_on((mod 2), [1, 2, 3], [2, 4, 3]) == Just (2, 4)
7395 // first_match_on((mod 2), [], [1, 2]) == Nothing
7396 template <typename ContainerIn1, typename ContainerIn2,
7397     typename F,
7398     typename X = typename ContainerIn1::value_type,
7399     typename Y = typename ContainerIn2::value_type,
7400     typename TOut = std::pair<X, Y>>
first_match_on(F f,const ContainerIn1 & xs,const ContainerIn2 & ys)7401 maybe<TOut> first_match_on(F f, const ContainerIn1& xs, const ContainerIn2& ys)
7402 {
7403     static_assert(std::is_same<X, Y>::value,
7404         "Both containers must have the same element type.");
7405     return first_match_by(is_equal_by(f), xs, ys);
7406 }
7407 
7408 // API search type: first_match_idx : ([a], [a]) -> Maybe Int
7409 // fwd bind count: 2
7410 // Find the first index of equal elements in the two sequences.
7411 // first_match_idx((==), [1, 2, 3], [5, 2, 3]) == 1
7412 // first_match_idx((==), [], [1, 2]) == Nothing
7413 template <typename ContainerIn1, typename ContainerIn2,
7414     typename X = typename ContainerIn1::value_type,
7415     typename Y = typename ContainerIn2::value_type>
first_match_idx(const ContainerIn1 & xs,const ContainerIn2 & ys)7416 maybe<std::size_t> first_match_idx(
7417     const ContainerIn1& xs, const ContainerIn2& ys)
7418 {
7419     static_assert(std::is_same<X, Y>::value,
7420         "Both containers must have the same element type.");
7421     return first_match_idx_by(std::equal_to<X>(), xs, ys);
7422 }
7423 
7424 // API search type: first_match : ([a], [a]) -> Maybe (a, a)
7425 // fwd bind count: 2
7426 // Find the first pair of equal elements in the two sequences.
7427 // first_match((==), [1, 2, 3], [5, 2, 3]) == Just (2, 2)
7428 // first_match((==), [], [1, 2]) == Nothing
7429 template <typename ContainerIn1, typename ContainerIn2,
7430     typename X = typename ContainerIn1::value_type,
7431     typename Y = typename ContainerIn2::value_type,
7432     typename TOut = std::pair<X, Y>>
first_match(const ContainerIn1 & xs,const ContainerIn2 & ys)7433 maybe<TOut> first_match(const ContainerIn1& xs, const ContainerIn2& ys)
7434 {
7435     static_assert(std::is_same<X, Y>::value,
7436         "Both containers must have the same element type.");
7437     return first_match_by(std::equal_to<X>(), xs, ys);
7438 }
7439 
7440 } // namespace fplus
7441 
7442 #include <algorithm>
7443 #include <cmath>
7444 #include <functional>
7445 #include <limits>
7446 #include <stdexcept>
7447 #include <type_traits>
7448 
7449 namespace fplus
7450 {
7451 
7452 // API search type: is_in_interval : (a, a, a) -> Bool
7453 // fwd bind count: 2
7454 // Checks if x is in [low, high), i.e. left-closed and right-open.
7455 template <typename T>
is_in_interval(const T & low,const T & high,const T & x)7456 bool is_in_interval(const T& low, const T& high, const T& x)
7457 {
7458     return (low <= x) && (x < high);
7459 }
7460 
7461 // API search type: is_in_interval_around : (a, a, a) -> Bool
7462 // fwd bind count: 2
7463 // Checks if x is in [center - radius, center + radius),
7464 // i.e. left-closed and right-open.
7465 template <typename T>
is_in_interval_around(const T & radius,const T & center,const T & x)7466 bool is_in_interval_around(const T& radius, const T& center, const T& x)
7467 {
7468     return is_in_interval(center - radius, center + radius, x);
7469 }
7470 
7471 // API search type: is_in_open_interval : (a, a, a) -> Bool
7472 // fwd bind count: 2
7473 // Checks if x is in (low, high), i.e. left-open and right-open.
7474 template <typename T>
is_in_open_interval(const T & low,const T & high,const T & x)7475 bool is_in_open_interval(const T& low, const T& high, const T& x)
7476 {
7477     return (low < x) && (x < high);
7478 }
7479 
7480 // API search type: is_in_open_interval_around : (a, a, a) -> Bool
7481 // fwd bind count: 2
7482 // Checks if x is in (center - radius, center + radius),
7483 // i.e. left-open and right-open.
7484 template <typename T>
is_in_open_interval_around(const T & radius,const T & center,const T & x)7485 bool is_in_open_interval_around(const T& radius, const T& center, const T& x)
7486 {
7487     return is_in_open_interval(center - radius, center + radius, x);
7488 }
7489 
7490 // API search type: is_in_closed_interval : (a, a, a) -> Bool
7491 // fwd bind count: 2
7492 // Checks if x is in [low, high], i.e. left-closed and right-closed.
7493 template <typename T>
is_in_closed_interval(const T & low,const T & high,const T & x)7494 bool is_in_closed_interval(const T& low, const T& high, const T& x)
7495 {
7496     return (low <= x) && (x <= high);
7497 }
7498 
7499 // API search type: is_in_closed_interval_around : (a, a, a) -> Bool
7500 // Checks if x is in [center - radius, center + radius],
7501 // i.e. left-closed and right-closed.
7502 template <typename T>
is_in_closed_interval_around(const T & radius,const T & center,const T & x)7503 bool is_in_closed_interval_around(const T& radius, const T& center, const T& x)
7504 {
7505     return is_in_closed_interval(center - radius, center + radius, x);
7506 }
7507 
7508 // API search type: reference_interval : (Float, Float, Float, Float, Float) -> Float
7509 // fwd bind count: 4
7510 // Linearly projects a value
7511 // from [old_low, old_high] into [new_low, new_high].
7512 // Does not clamp.
7513 // reference_interval(2, 6, 0, 4, 3) == 5
7514 // reference_interval(2, 10, 0, 4, 3) == 8
7515 // reference_interval(2, 6, 0, 4, -1) == 1
7516 // reference_interval(2, 10, 0, 4, -1) == 0
7517 template <typename T>
reference_interval(const T & new_low,const T & new_high,const T & old_low,const T & old_high,const T & x)7518 T reference_interval(const T& new_low, const T& new_high,
7519     const T& old_low, const T& old_high, const T& x)
7520 {
7521     const T scale = (new_high - new_low) / (old_high - old_low);
7522     return scale * (x - old_low) + new_low;
7523 }
7524 
7525 // API search type: clamp : (a, a, a) -> a
7526 // fwd bind count: 2
7527 // Puts value into [low, high], i.e. left-closed and right-closed.
7528 template <typename T>
clamp(const T & low,const T & high,const T & x)7529 T clamp(const T& low, const T& high, const T& x)
7530 {
7531     return std::max(low, std::min(high, x));
7532 }
7533 
7534 // API search type: is_negative : a -> Bool
7535 // fwd bind count: 0
7536 // Checks if x < 0.
7537 template <typename X>
is_negative(X x)7538 bool is_negative(X x)
7539 {
7540     return x < 0;
7541 }
7542 
7543 // API search type: is_positive : a -> Bool
7544 // fwd bind count: 0
7545 // Checks if x is not negative.
7546 template <typename X>
is_positive(X x)7547 bool is_positive(X x)
7548 {
7549     return !is_negative(x);
7550 }
7551 
7552 namespace internal
7553 {
7554     template <typename X>
7555     typename std::enable_if<std::is_unsigned<X>::value, X>::type
abs_helper(X x)7556     abs_helper(X x)
7557     {
7558         return x;
7559     }
7560 
7561     template <typename X>
7562     typename std::enable_if<!std::is_unsigned<X>::value, X>::type
abs_helper(X x)7563     abs_helper(X x)
7564     {
7565         return std::abs(x);
7566     }
7567 }
7568 
7569 // API search type: abs : a -> a
7570 // fwd bind count: 0
7571 // Returns the absolute (always non-negative) value of x.
7572 template <typename X>
abs(X x)7573 X abs(X x)
7574 {
7575     return internal::abs_helper(x);
7576 }
7577 
7578 // API search type: abs_diff : (a, a) -> a
7579 // fwd bind count: 1
7580 // Returns the absolute difference of two values.
7581 template <typename X>
abs_diff(X a,X b)7582 X abs_diff(X a, X b)
7583 {
7584     return a > b ? a - b : b - a;
7585 }
7586 
7587 // API search type: square : a -> a
7588 // fwd bind count: 0
7589 // Returns the square (x*x) of a value x.
7590 template <typename X>
square(X x)7591 X square(X x)
7592 {
7593     return x * x;
7594 }
7595 
7596 // API search type: cube : a -> a
7597 // fwd bind count: 0
7598 // Returns the cube (x*x*x) of a value x.
7599 template <typename X>
cube(X x)7600 X cube(X x)
7601 {
7602     return x * x * x;
7603 }
7604 
7605 // API search type: sign : a -> Int
7606 // fwd bind count: 0
7607 // Returns -1 for negative values, 1 otherwise.
7608 // sign(-3) == -1
7609 // sign(0) == 1
7610 // sign(16) == 1
7611 template <typename X>
sign(X x)7612 int sign(X x)
7613 {
7614     return is_negative(x) ? -1 : 1;
7615 }
7616 
7617 // API search type: sign_with_zero : a -> Int
7618 // fwd bind count: 0
7619 // Returns -1 for negative values, 0 for zero, 1 for positive values.
7620 // sign_with_zero(-3) == -1
7621 // sign_with_zero(0) == 0
7622 // sign_with_zero(16) == 1
7623 template <typename X>
sign_with_zero(X x)7624 int sign_with_zero(X x)
7625 {
7626     return x == 0 ? 0 : sign(x);
7627 }
7628 
7629 // API search type: integral_cast_throw : Int -> Int
7630 // fwd bind count: 0
7631 // Converts one integer type into another.
7632 // Throws an std::underflow_error or std::overflow_error
7633 // if the value does not fit into the destination type.
7634 template <typename Out, typename X>
7635 Out integral_cast_throw(X x)
7636 {
7637 #ifdef _MSC_VER
7638 __pragma(warning(push))
7639 __pragma(warning(disable:4127))
7640 #endif
7641     static_assert(std::is_integral<X>::value, "type must be integral");
7642     static_assert(std::is_integral<Out>::value, "type must be integral");
7643     if (std::is_signed<X>::value && std::is_signed<Out>::value)
7644     {
7645         if (static_cast<std::int64_t>(x) <
7646             static_cast<std::int64_t>(std::numeric_limits<Out>::lowest()))
7647         {
7648             throw std::underflow_error("");
7649         }
7650         if (static_cast<std::int64_t>(x) >
7651             static_cast<std::int64_t>(std::numeric_limits<Out>::max()))
7652         {
7653             throw std::overflow_error("");
7654         }
7655         return static_cast<Out>(x);
7656     }
7657     else if (!std::is_signed<X>::value && !std::is_signed<Out>::value)
7658     {
7659         if (static_cast<std::uint64_t>(x) <
7660             static_cast<std::uint64_t>(std::numeric_limits<Out>::lowest()))
7661         {
7662             throw std::underflow_error("");
7663         }
7664         if (static_cast<std::uint64_t>(x) >
7665             static_cast<std::uint64_t>(std::numeric_limits<Out>::max()))
7666         {
7667             throw std::overflow_error("");
7668         }
7669         return static_cast<Out>(x);
7670     }
7671     else if (std::is_signed<X>::value && !std::is_signed<Out>::value)
7672     {
7673         if (x < 0)
7674             return 0;
7675         if (static_cast<std::uint64_t>(x) >
7676             static_cast<std::uint64_t>(std::numeric_limits<Out>::max()))
7677         {
7678             throw std::overflow_error("");
7679         }
7680         return static_cast<Out>(x);
7681     }
7682     else if (!std::is_signed<X>::value && std::is_signed<Out>::value)
7683     {
7684         if (static_cast<std::uint64_t>(x) >
7685             static_cast<std::uint64_t>(std::numeric_limits<Out>::max()))
7686         {
7687             throw std::overflow_error("");
7688         }
7689         return static_cast<Out>(x);
7690     }
7691     else
7692     {
7693         assert(false);
7694         return static_cast<Out>(x);
7695     }
7696 #ifdef _MSC_VER
7697 __pragma(warning(pop))
7698 #endif
7699 }
7700 
7701 // API search type: integral_cast_clamp : Int -> Int
7702 // fwd bind count: 0
7703 // Converts one integer type into another.
7704 // If the value does not fit into the destination type,
7705 // the nearest possible value is used.
7706 // Also known as saturate_cast.
7707 template <typename Out, typename X>
7708 Out integral_cast_clamp(X x)
7709 {
7710     static_assert(std::is_integral<X>::value, "type must be integral");
7711     static_assert(std::is_integral<Out>::value, "type must be integral");
7712     if (std::is_signed<X>::value && std::is_signed<Out>::value)
7713     {
7714         if (static_cast<std::int64_t>(x) <
7715             static_cast<std::int64_t>(std::numeric_limits<Out>::lowest()))
7716         {
7717             return std::numeric_limits<Out>::lowest();
7718         }
7719         if (static_cast<std::int64_t>(x) >
7720             static_cast<std::int64_t>(std::numeric_limits<Out>::max()))
7721         {
7722             return std::numeric_limits<Out>::max();
7723         }
7724         return static_cast<Out>(x);
7725     }
7726     else if (!std::is_signed<X>::value && !std::is_signed<Out>::value)
7727     {
7728         if (static_cast<std::uint64_t>(x) <
7729             static_cast<std::uint64_t>(std::numeric_limits<Out>::lowest()))
7730         {
7731             return std::numeric_limits<Out>::lowest();
7732         }
7733         if (static_cast<std::uint64_t>(x) >
7734             static_cast<std::uint64_t>(std::numeric_limits<Out>::max()))
7735         {
7736             return std::numeric_limits<Out>::max();
7737         }
7738         return static_cast<Out>(x);
7739     }
7740     else if (std::is_signed<X>::value && !std::is_signed<Out>::value)
7741     {
7742         if (x < 0)
7743             return 0;
7744         if (static_cast<std::uint64_t>(x) >
7745             static_cast<std::uint64_t>(std::numeric_limits<Out>::max()))
7746         {
7747             return std::numeric_limits<Out>::max();
7748         }
7749         return static_cast<Out>(x);
7750     }
7751     else if (!std::is_signed<X>::value && std::is_signed<Out>::value)
7752     {
7753         if (static_cast<std::uint64_t>(x) >
7754             static_cast<std::uint64_t>(std::numeric_limits<Out>::max()))
7755         {
7756             return std::numeric_limits<Out>::max();
7757         }
7758         return static_cast<Out>(x);
7759     }
7760     else
7761     {
7762         assert(false);
7763         return static_cast<Out>(x);
7764     }
7765 }
7766 
7767 // API search type: round : a -> Int
7768 // fwd bind count: 0
7769 // Converts a value to the nearest integer.
7770 template <typename X, typename Out = int>
round(X x)7771 Out round(X x)
7772 {
7773     static_assert(!std::is_integral<X>::value, "type must be non-integral");
7774     static_assert(std::is_integral<Out>::value, "type must be integral");
7775     if (static_cast<double>(x) < static_cast<double>(std::numeric_limits<Out>::lowest()))
7776         return std::numeric_limits<Out>::lowest();
7777     if (static_cast<double>(x) > static_cast<double>(std::numeric_limits<Out>::max()))
7778         return std::numeric_limits<Out>::max();
7779     if (is_negative(x))
7780         x -= 1;
7781     return static_cast<Out>(x + 0.5);
7782 }
7783 
7784 // API search type: floor : a -> b
7785 // fwd bind count: 0
7786 // Converts a value to the nearest smaller integer.
7787 template <typename X, typename Out = int>
floor(X x)7788 Out floor(X x)
7789 {
7790     static_assert(!std::is_integral<X>::value, "type must be non-integral");
7791     static_assert(std::is_integral<Out>::value, "type must be integral");
7792     if (is_negative(x))
7793         x -= 1;
7794     return static_cast<Out>(x);
7795 }
7796 
7797 // API search type: floor_to_int_mult : (Int, Int) -> Int
7798 // fwd bind count: 1
7799 // Rounds an integer down to the nearest smaller or equal multiple of n.
7800 // n may not be zero.
7801 template <typename X>
floor_to_int_mult(X n,X x)7802 X floor_to_int_mult(X n, X x)
7803 {
7804     static_assert(std::is_integral<X>::value, "type must be integral");
7805     assert(n != 0);
7806     if (is_negative(n))
7807         n = abs(n);
7808     if (is_negative(x) && n != 1)
7809         x = static_cast<X>(x - 1);
7810     return static_cast<X>((x / n) * n);
7811 }
7812 
7813 // API search type: ceil_to_int_mult : (Int, Int) -> Int
7814 // fwd bind count: 1
7815 // Rounds an integer up to the nearest greater or equal multiple of n.
7816 // n may not be zero.
7817 template <typename X>
ceil_to_int_mult(X n,X x)7818 X ceil_to_int_mult(X n, X x)
7819 {
7820     return floor_to_int_mult(n, static_cast<X>(x + abs(n) - 1));
7821 }
7822 
7823 // API search type: ceil : a -> b
7824 // fwd bind count: 0
7825 // Converts a value to the nearest greater integer.
7826 template <typename X, typename Out = int>
ceil(X x)7827 Out ceil(X x)
7828 {
7829     static_assert(!std::is_integral<X>::value, "type must be non-integral");
7830     static_assert(std::is_integral<Out>::value, "type must be integral");
7831     return floor<X, Out>(x) + 1;
7832 }
7833 
7834 // API search type: int_power : (Int, Int) -> Int
7835 // fwd bind count: 1
7836 // integer power, only exponents >= 0
7837 template <typename X>
int_power(X base,X exp)7838 X int_power(X base, X exp)
7839 {
7840     static_assert(std::is_integral<X>::value,
7841         "type must be unsigned integral");
7842     assert(!is_negative(exp));
7843     if (exp == 0)
7844         return 1;
7845     if (exp == 1)
7846         return base;
7847     return base * int_power(base, exp - 1);
7848 }
7849 
7850 namespace internal
7851 {
7852     // minimum of x values after transformation
7853     // (has an overload for non-POD types)
7854     // min_on(mod2, 4, 3) == 4
7855     // min_on(mod7, 3, 5, 7, 3) == 7
7856     template <typename F, typename FirstT, typename... FIn>
helper_min_on(F f,const FirstT & first,const FIn &...v)7857     auto helper_min_on(F f, const FirstT& first, const FIn&... v) ->
7858         typename std::common_type<FirstT, FIn...>::type
7859     {
7860       using rettype = typename std::common_type<FirstT, FIn...>::type;
7861       using f_rettype = std::decay_t<internal::invoke_result_t<F, decltype(first)>>;
7862 
7863       rettype result = first;
7864       f_rettype result_trans = internal::invoke(f, first);
7865       f_rettype v_trans;
7866       unused(result_trans);
7867       unused(v_trans);
7868 
7869       (void)std::initializer_list<int>{
7870           ((v_trans = internal::invoke(f, v), v_trans < result_trans)
7871                ? (result = static_cast<rettype>(v), result_trans = v_trans, 0)
7872                : 0)...};
7873       return result;
7874     }
7875 
7876     template <typename F>
7877     struct helper_min_on_t
7878     {
helper_min_on_tfplus::internal::helper_min_on_t7879         helper_min_on_t(F _f) : f(_f) {}
7880         template <typename T, typename... Ts>
operator ()fplus::internal::helper_min_on_t7881         auto operator()(T&& x, Ts&&... xs) -> typename std::common_type<T, Ts...>::type
7882         {
7883             return helper_min_on(std::forward<F>(f), std::forward<T>(x), std::forward<Ts>(xs)...);
7884         }
7885     private:
7886         F f;
7887     };
7888 }
7889 
7890 // API search type: min_on : ((a -> b), a, a) -> a
7891 // minimum of x values after transformation (curried version)
7892 // min_on(mod2)(4, 3) == 4
7893 // min_on(mod7)(3, 5, 7, 3) == 7
7894 template <typename F>
min_on(F f)7895 auto min_on(F f) -> internal::helper_min_on_t<F>
7896 {
7897     return internal::helper_min_on_t<F>{f};
7898 }
7899 
7900 // API search type: min_2_on : ((a -> b), a, a) -> a
7901 // fwd bind count: 2
7902 // minimum of 2 values after transformation
7903 // min_2_on(mod2, 4, 3) == 4
7904 template <typename F, typename T>
min_2_on(F f,const T & x,const T & y)7905 T min_2_on(F f, const T& x, const T& y)
7906 {
7907     return internal::invoke(f, y) < internal::invoke(f, x) ? y : x;
7908 }
7909 
7910 namespace internal
7911 {
7912     // maximum of x values after transformation
7913     // (has an overload for non-POD types)
7914     // max_on(mod2, 4, 3) == 3
7915     // max_on(mod7, 3, 5, 7, 3) == 5
7916     template <typename F, typename FirstT, typename... FIn>
helper_max_on(F f,const FirstT & first,const FIn &...v)7917     auto helper_max_on(F f, const FirstT& first, const FIn&... v) ->
7918         typename std::common_type<FirstT, FIn...>::type
7919     {
7920       using rettype = typename std::common_type<FirstT, FIn...>::type;
7921       using f_rettype = decltype(f(first));
7922 
7923       rettype result = first;
7924       f_rettype result_trans = internal::invoke(f, first);
7925       f_rettype v_trans;
7926       unused(result_trans);
7927       unused(v_trans);
7928 
7929       (void)std::initializer_list<int>{
7930           ((v_trans = internal::invoke(f, v), v_trans > result_trans)
7931                ? (result = static_cast<rettype>(v), result_trans = v_trans, 0)
7932                : 0)...};
7933       return result;
7934     }
7935 
7936     template <typename F>
7937     struct helper_max_on_t
7938     {
helper_max_on_tfplus::internal::helper_max_on_t7939         helper_max_on_t(F _f) : f(_f) {}
7940         template <typename T, typename... Ts>
operator ()fplus::internal::helper_max_on_t7941         auto operator()(T&& x, Ts&&... xs) -> typename std::common_type<T, Ts...>::type
7942         {
7943             return helper_max_on(std::forward<F>(f), std::forward<T>(x), std::forward<Ts>(xs)...);
7944         }
7945     private:
7946         F f;
7947     };
7948 }
7949 
7950 // API search type: max_on : (a -> b) -> ((a, a) -> a)
7951 // maximum of x values after transformation (curried version)
7952 // (has an overload for non POD types)
7953 // max_on(mod2)(4, 3) == 3
7954 // max_on(mod7)(3, 5, 7, 3) == 5
7955 template <typename F>
max_on(F f)7956 auto max_on(F f) -> internal::helper_max_on_t<F>
7957 {
7958     return internal::helper_max_on_t<F>{f};
7959 }
7960 
7961 // API search type: max_2_on : ((a -> b), a, a) -> a
7962 // fwd bind count: 2
7963 // maximum of 2 values after transformation
7964 // max_2_on(mod2, 4, 3) == 3
7965 template <typename F, typename T>
max_2_on(F f,const T & x,const T & y)7966 T max_2_on(F f, const T& x, const T& y)
7967 {
7968     return internal::invoke(f, y) > internal::invoke(f, x) ? y : x;
7969 }
7970 
7971 // API search type: min : (a, a) -> a
7972 // Minimum of x number of values
7973 // min(4, 3) == 3
7974 // min(4, 3, 6, 2, 3) == 2
7975 template <typename U, typename... V>
min(const U & u,const V &...v)7976 auto min(const U& u, const V&... v) -> typename std::common_type<U, V...>::type
7977 {
7978   using rettype = typename std::common_type<U, V...>::type;
7979   rettype result = static_cast<rettype>(u);
7980   (void)std::initializer_list<int>{((v < result) ? (result = static_cast<rettype>(v), 0) : 0)...};
7981   return result;
7982 }
7983 
7984 // API search type: min_2 : (a, a) -> a
7985 // fwd bind count: 1
7986 // minimum of 2 values
7987 // min_2(4, 3) == 3
7988 template <typename T>
min_2(const T & x,const T & y)7989 T min_2(const T& x, const T& y)
7990 {
7991     return y < x ? y : x;
7992 }
7993 
7994 // API search type: max : (a, a) -> a
7995 // Maximum of x number of values.
7996 // max(4, 3) == 4
7997 // max(4, 3, 6, 2, 3) == 6
7998 template <typename U, typename... V>
max(const U & u,const V &...v)7999 auto max(const U& u, const V&... v) -> typename std::common_type<U, V...>::type
8000 {
8001   using rettype = typename std::common_type<U, V...>::type;
8002   rettype result = static_cast<rettype>(u);
8003   (void)std::initializer_list<int>{((v > result) ? (result = static_cast<rettype>(v), 0) : 0)...};
8004   return result;
8005 }
8006 
8007 // API search type: max_2 : (a, a) -> a
8008 // fwd bind count: 1
8009 // maximum of 2 values
8010 // max_2(4, 3) == 4
8011 template <typename T>
max_2(const T & x,const T & y)8012 T max_2(const T& x, const T& y)
8013 {
8014     return y > x ? y : x;
8015 }
8016 
8017 namespace internal
8018 {
8019     template <typename X>
8020     typename std::enable_if<std::is_floating_point<X>::value, X>::type
cyclic_value_helper_mod(X x,X y)8021     cyclic_value_helper_mod(X x, X y)
8022     {
8023         return std::fmod(x, y);
8024     }
8025 
8026     template <typename X>
8027     typename std::enable_if<std::is_integral<X>::value, X>::type
cyclic_value_helper_mod(X x,X y)8028     cyclic_value_helper_mod(X x, X y)
8029     {
8030         return x % y;
8031     }
8032 }
8033 
8034 // API search type: cyclic_value : a -> (a -> a)
8035 // Modulo for floating point values.
8036 // circumfence must be > 0
8037 // cyclic_value(8)(3) == 3
8038 // cyclic_value(8)(11) == 3
8039 // cyclic_value(8)(19) == 3
8040 // cyclic_value(8)(-2) == 6
8041 // cyclic_value(8)(-5) == 3
8042 // cyclic_value(8)(-13) == 3
8043 // Can be useful to normalize an angle into [0, 360]
8044 // For positive values it behaves like std::fmod with flipped arguments.
8045 template <typename X>
cyclic_value(X circumfence)8046 std::function<X(X)> cyclic_value(X circumfence)
8047 {
8048     assert(circumfence > 0);
8049     return [circumfence](X x) -> X
8050     {
8051         if (sign(x) < 0)
8052             return circumfence - internal::cyclic_value_helper_mod(
8053                 abs(x), abs(circumfence));
8054         else
8055             return internal::cyclic_value_helper_mod(
8056                 abs(x), abs(circumfence));
8057     };
8058 }
8059 
8060 // API search type: cyclic_difference : a -> ((a, a) -> a)
8061 // Returns the distance the first value has to advance forward on a circle
8062 // to reach the second value.
8063 // circumfence must be > 0
8064 // cyclic_difference(100)(5, 2) == 3
8065 // cyclic_difference(100)(2, 5) == 97
8066 // cyclic_difference(100)(3, -2) == 5
8067 // cyclic_difference(100)(-2, 3) == 95
8068 // cyclic_difference(100)(90, 10) == 80
8069 // cyclic_difference(100)(10, 90) == 20
8070 template <typename X>
cyclic_difference(X circumfence)8071 std::function<X(X, X)> cyclic_difference(X circumfence)
8072 {
8073     assert(circumfence > 0);
8074     return [circumfence](X a, X b) -> X
8075     {
8076         auto cyclic_value_f = cyclic_value(circumfence);
8077         const auto c_v_a = cyclic_value_f(a);
8078         const auto c_v_b = cyclic_value_f(b);
8079         return c_v_a > c_v_b ?
8080             c_v_a - c_v_b :
8081             circumfence + c_v_a - c_v_b;
8082     };
8083 }
8084 
8085 // API search type: cyclic_shortest_difference : a -> ((a, a) -> a)
8086 // Returns displacement (shortest way) the first value has to move on a circle
8087 // to reach the second value.
8088 // circumfence must be > 0
8089 // cyclic_shortest_difference(100)(5, 2) == 3
8090 // cyclic_shortest_difference(100)(2, 5) == -3
8091 // cyclic_shortest_difference(100)(3, -2) == 5
8092 // cyclic_shortest_difference(100)(-2, 3) == -5
8093 // cyclic_shortest_difference(100)(90, 10) == -20
8094 // cyclic_shortest_difference(100)(10, 90) == 20
8095 template <typename X>
cyclic_shortest_difference(X circumfence)8096 std::function<X(X, X)> cyclic_shortest_difference(X circumfence)
8097 {
8098     assert(circumfence > 0);
8099     return [circumfence](X a, X b) -> X
8100     {
8101         auto diff_func = cyclic_difference(circumfence);
8102         auto a_minus_b = diff_func(a, b);
8103         auto b_minus_a = diff_func(b, a);
8104         return a_minus_b <= b_minus_a ? a_minus_b : -b_minus_a;
8105     };
8106 }
8107 
8108 // API search type: cyclic_distance : a -> ((a, a) -> a)
8109 // Returns distance (shortest way) the first value has to move on a circle
8110 // to reach the second value.
8111 // circumfence must be > 0
8112 // cyclic_distance(100)(2, 5) == 3
8113 // cyclic_distance(100)(5, 2) == 3
8114 // cyclic_distance(100)(-2, 3) == 5
8115 // cyclic_distance(100)(3, -2) == 5
8116 // cyclic_distance(100)(10, 90) == 20
8117 // cyclic_distance(100)(90, 10) == 20
8118 // Can be useful to calculate the difference of two angles;
8119 template <typename X>
cyclic_distance(X circumfence)8120 std::function<X(X, X)> cyclic_distance(X circumfence)
8121 {
8122     assert(circumfence > 0);
8123     return [circumfence](X a, X b) -> X
8124     {
8125         auto diff_func = cyclic_difference(circumfence);
8126         auto a_minus_b = diff_func(a, b);
8127         auto b_minus_a = diff_func(b, a);
8128         return a_minus_b <= b_minus_a ? a_minus_b : b_minus_a;
8129     };
8130 }
8131 
8132 // API search type: pi : () -> Float
8133 // Pi.
pi()8134 constexpr inline double pi()
8135 {
8136     return 3.14159265358979323846;
8137 }
8138 
8139 // API search type: deg_to_rad : Float -> Float
8140 // fwd bind count: 0
8141 // converts degrees to radians
8142 template <typename T>
deg_to_rad(T x)8143 T deg_to_rad(T x)
8144 {
8145     static_assert(std::is_floating_point<T>::value, "Please use a floating-point type.");
8146     return static_cast<T>(x * pi() / 180.0);
8147 }
8148 
8149 // API search type: rad_to_deg : Float -> Float
8150 // fwd bind count: 0
8151 // converts radians to degrees
8152 template <typename T>
rad_to_deg(T x)8153 T rad_to_deg(T x)
8154 {
8155     static_assert(std::is_floating_point<T>::value, "Please use a floating-point type.");
8156     return static_cast<T>(x * 180.0 / pi());
8157 }
8158 
8159 namespace internal
8160 {
8161 
8162 template <typename Container, typename T>
8163 Container normalize_min_max(internal::reuse_container_t,
8164     const T& lower, const T& upper, Container&& xs)
8165 {
8166     assert(size_of_cont(xs) != 0);
8167     assert(lower <= upper);
8168     const auto minmax_it_p = std::minmax_element(std::begin(xs), std::end(xs));
8169     const T x_min = *minmax_it_p.first;
8170     const T x_max = *minmax_it_p.second;
8171     const auto f = [&](const T& x) -> T
__anon1e7ca4c43c02(const T& x) 8172     {
8173         return lower + (upper - lower) * (x - x_min) / (x_max - x_min);
8174     };
8175     std::transform(std::begin(xs), std::end(xs), std::begin(xs), f);
8176     return std::forward<Container>(xs);
8177 }
8178 
8179 template <typename Container, typename T>
8180 Container normalize_min_max(internal::create_new_container_t,
8181     const T& lower, const T& upper, const Container& xs)
8182 {
8183     auto ys = xs;
8184     return normalize_min_max(internal::reuse_container_t(),
8185         lower, upper, std::move(ys));
8186 }
8187 
8188 } // namespace internal
8189 
8190 // API search type: normalize_min_max : (a, a, [a]) -> [a]
8191 // fwd bind count: 2
8192 // Linearly scales the values into the given interval.
8193 // normalize_min_max(0, 10, [1, 3, 6]) == [0, 4, 10]
8194 // It is recommended to convert integers to double beforehand.
8195 template <typename Container,
8196     typename T = typename internal::remove_const_and_ref_t<Container>::value_type>
normalize_min_max(const T & lower,const T & upper,Container && xs)8197 auto normalize_min_max(const T& lower, const T& upper, Container&& xs)
8198 {
8199     return internal::normalize_min_max(internal::can_reuse_v<Container>{},
8200         lower, upper, std::forward<Container>(xs));
8201 }
8202 
8203 namespace internal
8204 {
8205 
8206 template <typename Container, typename T>
8207 Container normalize_mean_stddev(internal::reuse_container_t,
8208     const T& mean, const T& stddev, Container&& xs)
8209 {
8210     assert(size_of_cont(xs) != 0);
8211     const auto mean_and_stddev = fplus::mean_stddev<T>(xs);
8212     const auto f = [&](const T& x) -> T
__anon1e7ca4c43d02(const T& x) 8213     {
8214         return mean +
8215             stddev * (x - mean_and_stddev.first) / mean_and_stddev.second;
8216     };
8217     std::transform(std::begin(xs), std::end(xs), std::begin(xs), f);
8218     return std::forward<Container>(xs);
8219 }
8220 
8221 template <typename Container, typename T>
8222 Container normalize_mean_stddev(internal::create_new_container_t,
8223     const T& mean, const T& stddev, const Container& xs)
8224 {
8225     auto ys = xs;
8226     return normalize_mean_stddev(internal::reuse_container_t(),
8227         mean, stddev, std::move(ys));
8228 }
8229 
8230 } // namespace internal
8231 
8232 // API search type: normalize_mean_stddev : (a, a, [a]) -> [a]
8233 // fwd bind count: 2
8234 // Linearly scales the values
8235 // to match the given mean and population standard deviation.
8236 // normalize_mean_stddev(3, 2, [7, 8]) == [1, 5]
8237 template <typename Container,
8238     typename T = typename internal::remove_const_and_ref_t<Container>::value_type>
normalize_mean_stddev(const T & mean,const T & stddev,Container && xs)8239 auto normalize_mean_stddev(
8240     const T& mean, const T& stddev, Container&& xs)
8241 {
8242     return internal::normalize_mean_stddev(internal::can_reuse_v<Container>{},
8243         mean, stddev, std::forward<Container>(xs));
8244 }
8245 
8246 // API search type: standardize : [a] -> [a]
8247 // fwd bind count: 0
8248 // Linearly scales the values to zero mean and population standard deviation 1.
8249 // standardize([7, 8]) == [-1, 1]
8250 template <typename Container>
standardize(Container && xs)8251 auto standardize(Container&& xs)
8252 {
8253     typedef typename internal::remove_const_and_ref_t<Container>::value_type T;
8254     T mean(0);
8255     T stddev(1);
8256     return normalize_mean_stddev(mean, stddev, std::forward<Container>(xs));
8257 }
8258 
8259 // API search type: add_to : a -> (a -> a)
8260 // Provide a function adding to a given constant.
8261 // add_to(3)(2) == 5
8262 template <typename X>
add_to(const X & x)8263 std::function<X(X)> add_to(const X& x)
8264 {
8265     return [x](X y) -> X
8266     {
8267         return x + y;
8268     };
8269 }
8270 
8271 // API search type: subtract_from : a -> (a -> a)
8272 // Provide a function subtracting from a given constant.
8273 // subtract_from(3)(2) == 1
8274 template <typename X>
subtract_from(const X & x)8275 std::function<X(X)> subtract_from(const X& x)
8276 {
8277     return [x](X y) -> X
8278     {
8279         return x - y;
8280     };
8281 }
8282 
8283 // API search type: subtract : a -> (a -> a)
8284 // Provide a function subtracting a given constant.
8285 // subtract(2)(3) == 1
8286 template <typename X>
subtract(const X & x)8287 std::function<X(X)> subtract(const X& x)
8288 {
8289     return [x](X y) -> X
8290     {
8291         return y - x;
8292     };
8293 }
8294 
8295 // API search type: multiply_with : a -> (a -> a)
8296 // Provide a function multiplying with a given constant.
8297 // multiply_with(3)(2) == 6
8298 template <typename X>
multiply_with(const X & x)8299 std::function<X(X)> multiply_with(const X& x)
8300 {
8301     return [x](X y) -> X
8302     {
8303         return y * x;
8304     };
8305 }
8306 
8307 // API search type: divide_by : a -> (a -> a)
8308 // Provide a function dividing by a given constant.
8309 // divide_by(2)(6) == 3
8310 template <typename X>
divide_by(const X & x)8311 std::function<X(X)> divide_by(const X& x)
8312 {
8313     return [x](X y) -> X
8314     {
8315         return y / x;
8316     };
8317 }
8318 
8319 // API search type: histogram_using_intervals : ([(a, a)], [a]) -> [((a, a), Int)]
8320 // fwd bind count: 1
8321 // Generate a histogram of a sequence with given bins.
8322 // histogram_using_intervals([(0,4), (4,5), (6,8)], [0,1,4,5,6,7,8,9]) ==
8323 //     [((0, 4), 2), ((4, 5), 1), ((6, 8), 2)]
8324 template <typename ContainerIn,
8325         typename ContainerIntervals,
8326         typename ContainerOut =
8327             std::vector<
8328                 std::pair<
8329                     typename ContainerIntervals::value_type,
8330                     std::size_t>>,
8331         typename T = typename ContainerIn::value_type>
8332 ContainerOut histogram_using_intervals(
8333         const ContainerIntervals& intervals, const ContainerIn& xs)
8334 {
8335     ContainerOut bins;
8336     internal::prepare_container(bins, size_of_cont(intervals));
8337     auto itOut = internal::get_back_inserter(bins);
8338     for (const auto& interval : intervals)
8339     {
8340         *itOut = std::make_pair(interval, 0);
8341     }
8342     for (const auto& x : xs)
8343     {
8344         for (auto& bin : bins)
8345         {
8346             if (x >= bin.first.first && x < bin.first.second)
8347             {
8348                 ++bin.second;
8349             }
8350         }
8351     }
8352     return bins;
8353 }
8354 
8355 // API search type: generate_consecutive_intervals : (a, a, a) -> [(a, a)]
8356 // fwd bind count: 2
8357 // Return intervals of a given size adjacent to each other
8358 // generate_consecutive_intervals(0, 2, 4) == [(0,2), (2,4), (4,6), (6,8)]
8359 template <typename T>
generate_consecutive_intervals(const T & first_lower_bound,const T & step,std::size_t count)8360 std::vector<std::pair<T, T>> generate_consecutive_intervals(
8361         const T& first_lower_bound, const T& step, std::size_t count)
8362 {
8363     const auto count_as_T = static_cast<T>(count);
8364     return zip(
8365         numbers_step<T>(
8366             first_lower_bound,
8367             first_lower_bound + count_as_T * step,
8368             step),
8369         numbers_step<T>(
8370             first_lower_bound + step,
8371             first_lower_bound + step + count_as_T * step,
8372             step));
8373 }
8374 
8375 // API search type: histogram : (a, a, a, [a]) -> [((a, a), Int)]
8376 // fwd bind count: 3
8377 // Calculate the histogram of a sequence using a given bin width.
8378 // histogram(1, 2, 4, [0,1,4,5,7,8,9]) == [(1, 2), (3, 0), (5, 2), (7, 1)]
8379 template <typename ContainerIn,
8380         typename ContainerOut =
8381             std::vector<
8382                 std::pair<
8383                     typename ContainerIn::value_type,
8384                     std::size_t>>,
8385         typename T = typename ContainerIn::value_type>
8386 ContainerOut histogram(
8387         const T& first_center, const T& bin_width, std::size_t count,
8388         const ContainerIn& xs)
8389 {
8390     const auto interval_histogram = histogram_using_intervals(
8391         generate_consecutive_intervals(
8392             first_center - bin_width / 2,
8393             bin_width,
8394             count),
8395         xs);
8396 
8397     assert(size_of_cont(interval_histogram) == count);
8398 
8399     ContainerOut histo;
8400     internal::prepare_container(histo, count);
8401     auto itOut = internal::get_back_inserter(histo);
8402     for (const auto& bin : interval_histogram)
8403     {
8404         const auto current_center = (bin.first.first + bin.first.second) / 2;
8405         *itOut = std::make_pair(current_center, bin.second);
8406     }
8407     return histo;
8408 }
8409 
8410 // API search type: modulo_chain : ([Int], Int) -> [Int]
8411 // fwd bind count: 1
8412 // For every factor (value % factor) is pushed into the result,
8413 // and value is divided by this factor for the next iteration.
8414 // Can be useful to convert a time in seconds
8415 // into hours, minutes and seconds and similar calculations.
8416 // modulo_chain([24, 60, 60], 7223) == [0, 2, 0, 23]
8417 template <typename T>
modulo_chain(const std::vector<T> & factors,T val)8418 std::vector<T> modulo_chain(const std::vector<T>& factors, T val)
8419 {
8420     std::vector<T> result;
8421     result.reserve(factors.size());
8422     const auto factors_reversed = reverse(factors);
8423     for (const auto& factor : factors_reversed)
8424     {
8425         result.push_back(val % factor);
8426         val /= factor;
8427     }
8428     result.push_back(val);
8429     return reverse(result);
8430 }
8431 
8432 // API search type: line_equation : ((Float, Float), (Float, Float), Float) -> Float
8433 // fwd bind count: 2
8434 // Can be used to interpolate and to extrapolate
8435 // based on two given two-dimensional points (x, y).
8436 // Using slope, return NaN if x_1 == x_2.
8437 // line_equation((0.0, 0.0), (2.0, 1.0), 3.0) == 1.5
8438 // line_equation((-1.0, 1.0), (-2.0, 4.0), 0.0) == -2.0
8439 template <typename T>
line_equation(const std::pair<T,T> & a,const std::pair<T,T> & b,T x)8440 T line_equation(const std::pair<T, T>& a, const std::pair<T, T>& b, T x)
8441 {
8442     static_assert(std::is_floating_point<T>::value, "Please use a floating-point type.");
8443     const double m = (b.second - a.second) / (b.first - a.first);
8444     return m * x + a.second - m * a.first;
8445 }
8446 
8447 } // namespace fplus
8448 
8449 //
8450 // search.hpp
8451 //
8452 
8453 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
8454 // https://github.com/Dobiasd/FunctionalPlus
8455 // Distributed under the Boost Software License, Version 1.0.
8456 // (See accompanying file LICENSE_1_0.txt or copy at
8457 //  http://www.boost.org/LICENSE_1_0.txt)
8458 
8459 
8460 
8461 #include <algorithm>
8462 
8463 namespace fplus
8464 {
8465 
8466 // API search type: find_first_by : ((a -> Bool), [a]) -> Maybe a
8467 // fwd bind count: 1
8468 // Returns the first element fulfilling the predicate.
8469 // find_first_by(is_even, [1, 3, 4, 6, 9]) == Just(4)
8470 // find_first_by(is_even, [1, 3, 5, 7, 9]) == Nothing
8471 template <typename Container, typename UnaryPredicate,
8472     typename T = typename Container::value_type>
find_first_by(UnaryPredicate pred,const Container & xs)8473 maybe<T> find_first_by(UnaryPredicate pred, const Container& xs)
8474 {
8475     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
8476     auto it = std::find_if(std::begin(xs), std::end(xs), pred);
8477     if (it == std::end(xs))
8478         return nothing<T>();
8479     return just<T>(*it);
8480 }
8481 
8482 // API search type: find_last_by : ((a -> Bool), [a]) -> Maybe a
8483 // fwd bind count: 1
8484 // Returns the last element fulfilling the predicate.
8485 // find_last_by(is_even, [1, 3, 4, 6, 9]) == Just(6)
8486 // find_last_by(is_even, [1, 3, 5, 7, 9]) == Nothing
8487 template <typename Container, typename UnaryPredicate,
8488     typename T = typename Container::value_type>
find_last_by(UnaryPredicate pred,const Container & xs)8489 maybe<T> find_last_by(UnaryPredicate pred, const Container& xs)
8490 {
8491     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
8492     return find_first_by(pred, reverse(xs));
8493 }
8494 
8495 // API search type: find_first_idx_by : ((a -> Bool), [a]) -> Maybe Int
8496 // fwd bind count: 1
8497 // Returns the index of the first element fulfilling the predicate.
8498 // find_first_idx_by(is_even, [1, 3, 4, 6, 9]) == Just(2)
8499 // find_first_idx_by(is_even, [1, 3, 5, 7, 9]) == Nothing
8500 template <typename Container, typename UnaryPredicate>
find_first_idx_by(UnaryPredicate pred,const Container & xs)8501 maybe<std::size_t> find_first_idx_by
8502         (UnaryPredicate pred, const Container& xs)
8503 {
8504     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
8505     auto it = std::find_if(std::begin(xs), std::end(xs), pred);
8506     if (it == std::end(xs))
8507         return nothing<std::size_t>();
8508     return static_cast<std::size_t>(std::distance(std::begin(xs), it));
8509 }
8510 
8511 // API search type: find_last_idx_by : ((a -> Bool), [a]) -> Maybe Int
8512 // fwd bind count: 1
8513 // Returns the index of the last element fulfilling the predicate.
8514 // find_last_idx_by(is_even, [1, 3, 4, 6, 9]) == Just(3)
8515 // find_last_idx_by(is_even, [1, 3, 5, 7, 9]) == Nothing
8516 template <typename Container, typename UnaryPredicate>
find_last_idx_by(UnaryPredicate pred,const Container & xs)8517 maybe<std::size_t> find_last_idx_by
8518         (UnaryPredicate pred, const Container& xs)
8519 {
8520     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
8521     auto calcRevIdx = [&](std::size_t idx)
8522     {
8523         return size_of_cont(xs) - (idx + 1);
8524     };
8525     return lift_maybe(calcRevIdx, find_first_idx_by(pred, reverse(xs)));
8526 }
8527 
8528 // API search type: find_first_idx : (a, [a]) -> Maybe Int
8529 // fwd bind count: 1
8530 // Returns the index of the first element equal to x.
8531 // find_first_idx(4, [1, 3, 4, 4, 9]) == Just(2)
8532 // find_first_idx(4, [1, 3, 5, 7, 9]) == Nothing
8533 template <typename Container>
find_first_idx(const typename Container::value_type & x,const Container & xs)8534 maybe<std::size_t> find_first_idx
8535         (const typename Container::value_type& x, const Container& xs)
8536 {
8537     return find_first_idx_by(is_equal_to(x), xs);
8538 }
8539 
8540 // API search type: find_last_idx : (a, [a]) -> Maybe Int
8541 // fwd bind count: 1
8542 // Returns the index of the last element equal to x.
8543 // find_last_idx(4, [1, 3, 4, 4, 9]) == Just(3)
8544 // find_last_idx(4, [1, 3, 5, 7, 9]) == Nothing
8545 template <typename Container>
find_last_idx(const typename Container::value_type & x,const Container & xs)8546 maybe<std::size_t> find_last_idx
8547         (const typename Container::value_type& x, const Container& xs)
8548 {
8549     return find_last_idx_by(is_equal_to(x), xs);
8550 }
8551 
8552 // API search type: find_all_idxs_by : ((a -> Bool), [a]) -> [Int]
8553 // fwd bind count: 1
8554 // Returns the indices off all elements fulfilling the predicate.
8555 // find_all_idxs_by(is_even, [1, 3, 4, 6, 9]) == [2, 3]
8556 template <typename ContainerOut = std::vector<std::size_t>,
8557         typename UnaryPredicate, typename Container>
8558 ContainerOut find_all_idxs_by(UnaryPredicate p, const Container& xs)
8559 {
8560     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
8561     std::size_t idx = 0;
8562     ContainerOut result;
8563     auto itOut = internal::get_back_inserter(result);
8564     for (const auto& x : xs)
8565     {
8566         if (internal::invoke(p, x))
8567             *itOut = idx;
8568         ++idx;
8569     }
8570     return result;
8571 }
8572 
8573 // API search type: find_all_idxs_of : (a, [a]) -> [Int]
8574 // fwd bind count: 1
8575 // Returns the indices off all elements equal to x.
8576 // find_all_idxs_of(4, [1, 3, 4, 4, 9]) == [2, 3]
8577 template <typename ContainerOut = std::vector<std::size_t>,
8578         typename Container,
8579         typename T = typename Container::value_type>
8580 ContainerOut find_all_idxs_of
8581         (const T& x, const Container& xs)
8582 {
8583     return find_all_idxs_by(is_equal_to(x), xs);
8584 }
8585 
8586 // API search type: find_all_instances_of_token : ([a], [a]) -> [Int]
8587 // fwd bind count: 1
8588 // Returns the starting indices of all segments matching token.
8589 // find_all_instances_of_token("haha", "oh, hahaha!") == [4, 6]
8590 template <typename ContainerOut =
8591     std::vector<std::size_t>, typename Container>
8592 ContainerOut find_all_instances_of_token(const Container& token,
8593         const Container& xs)
8594 {
8595     if (size_of_cont(token) > size_of_cont(xs))
8596         return ContainerOut();
8597 
8598     auto itInBegin = std::begin(xs);
8599     auto itInEnd = itInBegin;
8600     internal::advance_iterator(itInEnd, size_of_cont(token));
8601     std::size_t idx = 0;
8602     ContainerOut result;
8603     auto outIt = internal::get_back_inserter(result);
8604     std::size_t last_possible_idx = size_of_cont(xs) - size_of_cont(token);
8605     auto check_and_push = [&]()
__anon1e7ca4c44402() 8606     {
8607         if (std::equal(itInBegin, itInEnd, std::begin(token)))
8608         {
8609             *outIt = idx;
8610         }
8611     };
8612     while (idx != last_possible_idx)
8613     {
8614         check_and_push();
8615         ++itInBegin;
8616         ++itInEnd;
8617         ++idx;
8618     }
8619     check_and_push();
8620     return result;
8621 }
8622 
8623 // API search type: find_all_instances_of_token_non_overlapping : ([a], [a]) -> [Int]
8624 // fwd bind count: 1
8625 // Returns the starting indices
8626 // of all non-overlapping segments matching token.
8627 // find_all_instances_of_token_non_overlapping("haha", "oh, hahaha!") == [4]
8628 template <typename ContainerOut = std::vector<std::size_t>, typename Container>
8629 ContainerOut find_all_instances_of_token_non_overlapping
8630         (const Container& token, const Container& xs)
8631 {
8632     auto overlapping_instances = find_all_instances_of_token<ContainerOut>(
8633             token, xs);
8634     ContainerOut result;
8635     auto outIt = internal::get_back_inserter(result);
8636     std::size_t token_size = size_of_cont(token);
8637     for (const auto idx : overlapping_instances)
8638     {
8639         if (result.empty() || result.back() + token_size <= idx)
8640         {
8641             *outIt = idx;
8642         }
8643     }
8644     return result;
8645 }
8646 
8647 // API search type: find_first_instance_of_token : ([a], [a]) -> Maybe Int
8648 // fwd bind count: 1
8649 // Returns the index of the first segment matching token.
8650 // find_first_instance_of_token("haha", "oh, hahaha!") == just 4
8651 template <typename Container>
find_first_instance_of_token(const Container & token,const Container & xs)8652 maybe<std::size_t> find_first_instance_of_token
8653         (const Container& token, const Container& xs)
8654 {
8655     if (size_of_cont(token) > size_of_cont(xs))
8656         return nothing<std::size_t>();
8657 
8658     auto itInBegin = std::begin(xs);
8659     auto itInEnd = itInBegin;
8660     internal::advance_iterator(itInEnd, size_of_cont(token));
8661     std::size_t idx = 0;
8662     std::size_t last_possible_idx = size_of_cont(xs) - size_of_cont(token);
8663     while (idx != last_possible_idx)
8664     {
8665         if (std::equal(itInBegin, itInEnd, std::begin(token)))
8666         {
8667             return just(idx);
8668         }
8669         ++itInBegin;
8670         ++itInEnd;
8671         ++idx;
8672     }
8673     if (std::equal(itInBegin, itInEnd, std::begin(token)))
8674     {
8675         return just(idx);
8676     }
8677     return nothing<std::size_t>();
8678 }
8679 
8680 } // namespace fplus
8681 
8682 //
8683 // sets.hpp
8684 //
8685 
8686 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
8687 // https://github.com/Dobiasd/FunctionalPlus
8688 // Distributed under the Boost Software License, Version 1.0.
8689 // (See accompanying file LICENSE_1_0.txt or copy at
8690 //  http://www.boost.org/LICENSE_1_0.txt)
8691 
8692 
8693 
8694 #include <algorithm>
8695 #include <set>
8696 #include <unordered_set>
8697 
8698 namespace fplus
8699 {
8700 
8701 // API search type: set_includes : (Set a, Set a) -> Bool
8702 // fwd bind count: 1
8703 // Checks if every element of the second set is also present in the first set.
8704 // Also known as is_subset_of.
8705 template <typename SetType>
set_includes(const SetType & set1,const SetType & set2)8706 bool set_includes(const SetType& set1, const SetType& set2)
8707 {
8708     return std::includes(std::begin(set1), std::end(set1),
8709         std::begin(set2), std::end(set2));
8710 }
8711 
8712 // API search type: unordered_set_includes : (Unordered_Set a, Unordered_Set a) -> Bool
8713 // fwd bind count: 1
8714 // Checks if every element of the second unordered_set
8715 // is also present in the first unordered_set.
8716 // Also known as is_subset_of.
8717 template <typename UnorderSetType>
unordered_set_includes(const UnorderSetType & set1,const UnorderSetType & set2)8718 bool unordered_set_includes(const UnorderSetType& set1,
8719                             const UnorderSetType& set2)
8720 {
8721     auto first_not_included = std::find_if(set2.begin(), set2.end(),
8722         [&](const typename UnorderSetType::value_type& x)
8723         -> bool { return set1.find(x) == set1.end();});
8724     return first_not_included == set2.end();
8725 }
8726 
8727 // API search type: set_merge : (Set a, Set a) -> Set a
8728 // fwd bind count: 1
8729 // Returns the union of two given sets.
8730 template <typename SetType>
set_merge(const SetType & set1,const SetType & set2)8731 SetType set_merge(const SetType& set1, const SetType& set2)
8732 {
8733     SetType result;
8734     auto itOut = internal::get_back_inserter(result);
8735     std::merge(std::begin(set1), std::end(set1),
8736         std::begin(set2), std::end(set2),
8737         itOut);
8738     return result;
8739 }
8740 
8741 // API search type: unordered_set_merge : (Unordered_Set a, Unordered_Set a) -> Unordered_Set a
8742 // fwd bind count: 1
8743 // Returns the union of two given sets.
8744 template <typename UnorderSetType>
unordered_set_merge(const UnorderSetType & set1,const UnorderSetType & set2)8745 UnorderSetType unordered_set_merge(const UnorderSetType& set1, const UnorderSetType& set2)
8746 {
8747     UnorderSetType result;
8748     auto itOut = internal::get_back_inserter(result);
8749     std::copy(std::begin(set1), std::end(set1), itOut);
8750     std::copy(std::begin(set2), std::end(set2), itOut);
8751     return result;
8752 }
8753 
8754 // API search type: set_intersection : (Set a, Set a) -> Set a
8755 // fwd bind count: 1
8756 // Returns the intersection of both sets.
8757 template <typename SetType>
set_intersection(const SetType & set1,const SetType & set2)8758 SetType set_intersection(const SetType& set1, const SetType& set2)
8759 {
8760     SetType result;
8761     auto itOut = internal::get_back_inserter(result);
8762     std::set_intersection(std::begin(set1), std::end(set1),
8763         std::begin(set2), std::end(set2),
8764         itOut);
8765     return result;
8766 }
8767 
8768 // API search type: unordered_set_intersection : (Unordered_Set a, Unordered_Set a) -> Unordered_Set a
8769 // fwd bind count: 1
8770 // Returns the intersection of both unordered_sets.
8771 template <typename UnorderSetType>
unordered_set_intersection(const UnorderSetType & set1,const UnorderSetType & set2)8772 UnorderSetType unordered_set_intersection(
8773     const UnorderSetType& set1, const UnorderSetType& set2)
8774 {
8775     UnorderSetType result;
8776     auto itOut = internal::get_back_inserter(result);
8777     std::copy_if(std::begin(set2), std::end(set2),
8778         itOut, [&](const typename UnorderSetType::value_type &x)
8779         -> bool {return set1.find(x) != set1.end();});
8780     return result;
8781 }
8782 
8783 // API search type: set_is_disjoint : (Set a, Set a) -> Bool
8784 // fwd bind count: 1
8785 // Checks if two sets are disjoint.
8786 template <typename SetType>
set_is_disjoint(const SetType & set1,const SetType & set2)8787 bool set_is_disjoint(const SetType& set1, const SetType& set2)
8788 {
8789     return set_intersection(set1, set2).empty();
8790 }
8791 
8792 // API search type: unordered_set_is_disjoint : (Unordered_Set a, Unordered_Set a) -> Bool
8793 // fwd bind count: 1
8794 // Checks if two unordered_sets are disjoint.
8795 template <typename UnorderSetType>
unordered_set_is_disjoint(const UnorderSetType & set1,const UnorderSetType & set2)8796 bool unordered_set_is_disjoint(
8797     const UnorderSetType& set1, const UnorderSetType& set2)
8798 {
8799     return unordered_set_intersection(set1, set2).empty();
8800 }
8801 
8802 // API search type: set_difference : (Set a, Set a) -> Set a
8803 // fwd bind count: 1
8804 // Returns the elements in set1 that are not present in set2.
8805 template <typename SetType>
set_difference(const SetType & set1,const SetType & set2)8806 SetType set_difference(const SetType& set1, const SetType& set2)
8807 {
8808     SetType result;
8809     auto itOut = internal::get_back_inserter(result);
8810     std::set_difference(std::begin(set1), std::end(set1),
8811         std::begin(set2), std::end(set2),
8812         itOut);
8813     return result;
8814 }
8815 
8816 // API search type: unordered_set_difference : (Unordered_Set a, Unordered_Set a) -> Unordered_Set a
8817 // fwd bind count: 1
8818 // Returns the elements in unordered_set1
8819 // that are not present in unordered_set2.
8820 template <typename UnorderSetType>
unordered_set_difference(const UnorderSetType & set1,const UnorderSetType & set2)8821 UnorderSetType unordered_set_difference(const UnorderSetType& set1,
8822 const UnorderSetType& set2)
8823 {
8824     UnorderSetType result;
8825     auto itOut = internal::get_back_inserter(result);
8826     std::copy_if(std::begin(set1), std::end(set1),
8827         itOut, [&](const typename UnorderSetType::value_type &x)
8828         -> bool {return set2.find(x) == set2.end();});
8829     return result;
8830 }
8831 
8832 // API search type: set_symmetric_difference : (Set a, Set a) -> Set a
8833 // fwd bind count: 1
8834 // Returns the symmetric difference of both sets.
8835 template <typename SetType>
set_symmetric_difference(const SetType & set1,const SetType & set2)8836 SetType set_symmetric_difference(const SetType& set1, const SetType& set2)
8837 {
8838     SetType result;
8839     auto itOut = internal::get_back_inserter(result);
8840     std::set_symmetric_difference(std::begin(set1), std::end(set1),
8841         std::begin(set2), std::end(set2),
8842         itOut);
8843     return result;
8844 }
8845 
8846 // API search type: unordered_set_symmetric_difference : (Unordered_Set a, Unordered_Set a) -> Unordered_Set a
8847 // fwd bind count: 1
8848 // Returns the symmetric difference of both unordered_sets.
8849 template <typename UnorderSetType>
unordered_set_symmetric_difference(const UnorderSetType & set1,const UnorderSetType & set2)8850 UnorderSetType unordered_set_symmetric_difference(
8851     const UnorderSetType& set1, const UnorderSetType& set2)
8852 {
8853     UnorderSetType result;
8854     auto itOut = internal::get_back_inserter(result);
8855     std::copy_if(std::begin(set1), std::end(set1),
8856         itOut, [&](const typename UnorderSetType::value_type &x)
8857         -> bool {return set2.find(x) == set2.end();});
8858     std::copy_if(std::begin(set2), std::end(set2),
8859         itOut, [&](const typename UnorderSetType::value_type &x)
8860         -> bool {return set1.find(x) == set1.end();});
8861     return result;
8862 }
8863 
8864 // API search type: sets_intersection : [Set a] -> Set a
8865 // fwd bind count: 0
8866 // Returns the intersection of the given sets.
8867 // Also known as intersect_many.
8868 // For performance try to sort the inputs sets prior, ascendending by size.
8869 template <typename ContainerIn,
8870     typename SetType = typename ContainerIn::value_type>
sets_intersection(const ContainerIn & sets)8871 SetType sets_intersection(const ContainerIn& sets)
8872 {
8873     return fold_left_1(set_intersection<SetType>, sets);
8874 }
8875 
8876 // API search type: unordered_sets_intersection : [Unordered_Set a] -> Unordered_Set a
8877 // fwd bind count: 0
8878 // Returns the intersection of the given unordered_sets.
8879 // Also known as intersect_many.
8880 template <typename ContainerIn,
8881     typename UnordSetType = typename ContainerIn::value_type>
unordered_sets_intersection(const ContainerIn & sets)8882 UnordSetType unordered_sets_intersection(const ContainerIn& sets)
8883 {
8884     return fold_left_1(unordered_set_intersection<UnordSetType>, sets);
8885 }
8886 
8887 } // namespace fplus
8888 
8889 
8890 #include <algorithm>
8891 #include <numeric>
8892 #include <type_traits>
8893 
8894 namespace fplus
8895 {
8896 
8897 // API search type: any_by : ((a -> Bool), [a]) -> Bool
8898 // fwd bind count: 1
8899 // Check if all elements in a container fulfill a predicate.
8900 // any_by(is_odd, [2, 4, 6]) == false
8901 template <typename UnaryPredicate, typename Container>
any_by(UnaryPredicate p,const Container & xs)8902 bool any_by(UnaryPredicate p, const Container& xs)
8903 {
8904     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
8905     return std::any_of(std::begin(xs), std::end(xs), p);
8906 }
8907 
8908 // API search type: any : [Bool] -> Bool
8909 // fwd bind count: 0
8910 // Checks if all elements in a container are true.
8911 // any([false, true, false]) == true
8912 template <typename Container>
any(const Container & xs)8913 bool any(const Container& xs)
8914 {
8915     typedef typename Container::value_type T;
8916     return any_by(identity<T>, xs);
8917 }
8918 
8919 // API search type: none_by : ((a -> Bool), [a]) -> Bool
8920 // fwd bind count: 1
8921 // Check no element in a container fulfills a predicate.
8922 // none_by(is_even, [3, 4, 5]) == false
8923 template <typename UnaryPredicate, typename Container>
none_by(UnaryPredicate p,const Container & xs)8924 bool none_by(UnaryPredicate p, const Container& xs)
8925 {
8926     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
8927     return std::none_of(std::begin(xs), std::end(xs), p);
8928 }
8929 
8930 // API search type: none : [Bool] -> Bool
8931 // fwd bind count: 0
8932 // Checks if all elements in a container are false.
8933 // none([false, true, false]) == false
8934 template <typename Container>
none(const Container & xs)8935 bool none(const Container& xs)
8936 {
8937     typedef typename Container::value_type T;
8938     return none_by(identity<T>, xs);
8939 }
8940 
8941 
8942 // API search type: minimum_idx_by : (((a, a) -> Bool), [a]) -> Int
8943 // fwd bind count: 1
8944 // Return the index of the first minimum element using a less comparator.
8945 // minimum_idx_by(lessLength, ["123", "12", "1234", "123"]) -> "1"
8946 // Unsafe! Crashes on an empty sequence.
8947 template <typename Compare, typename Container>
minimum_idx_by(Compare comp,const Container & xs)8948 typename std::size_t minimum_idx_by(Compare comp,
8949         const Container& xs)
8950 {
8951     internal::check_compare_for_container<Compare, Container>();
8952     assert(is_not_empty(xs));
8953     return static_cast<std::size_t>(std::distance(std::begin(xs),
8954         std::min_element(std::begin(xs), std::end(xs), comp)));
8955 }
8956 
8957 // API search type: minimum_idx_by_maybe : (((a, a) -> Bool), [a]) -> Int
8958 // fwd bind count: 1
8959 // Return the index of the first minimum element using a less comparator
8960 // if sequence is not empty.
8961 // minimum_idx_by_maybe(lessLength, ["123", "12", "1234", "123"]) -> Just "1"
8962 // minimum_idx_by_maybe(lessLength, []) -> Nothing
8963 template <typename Compare, typename Container>
minimum_idx_by_maybe(Compare comp,const Container & xs)8964 maybe<typename std::size_t> minimum_idx_by_maybe(Compare comp,
8965         const Container& xs)
8966 {
8967     if (is_empty(xs))
8968         return {};
8969     else
8970         return minimum_idx_by(comp, xs);
8971 }
8972 
8973 // API search type: maximum_idx_by : (((a, a) -> Bool), [a]) -> Int
8974 // fwd bind count: 1
8975 // Return the index of the first maximum element using a less comparator.
8976 // maximum_idx_by(lessLength, ["123", "12", "1234", "123"]) == "2"
8977 // Unsafe! Crashes on an empty sequence.
8978 template <typename Compare, typename Container>
maximum_idx_by(Compare comp,const Container & xs)8979 typename std::size_t maximum_idx_by(Compare comp,
8980         const Container& xs)
8981 {
8982     internal::check_compare_for_container<Compare, Container>();
8983     assert(is_not_empty(xs));
8984     return static_cast<std::size_t>(std::distance(std::begin(xs),
8985         std::max_element(std::begin(xs), std::end(xs), comp)));
8986 }
8987 
8988 // API search type: maximum_idx_by_maybe : (((a, a) -> Bool), [a]) -> Maybe Int
8989 // fwd bind count: 1
8990 // Return the index of the first maximum element using a less comparator
8991 // if sequence is not empty.
8992 // maximum_idx_by_maybe(lessLength, ["123", "12", "1234", "123"]) == Just "2"
8993 // maximum_idx_by_maybe(lessLength, []) == Nothing
8994 template <typename Compare, typename Container>
maximum_idx_by_maybe(Compare comp,const Container & xs)8995 maybe<typename std::size_t> maximum_idx_by_maybe(Compare comp,
8996         const Container& xs)
8997 {
8998     if (is_empty(xs))
8999         return {};
9000     else
9001         return maximum_idx_by(comp, xs);
9002 }
9003 
9004 
9005 // API search type: minimum_idx : [a] -> Int
9006 // fwd bind count: 0
9007 // Return the index of the first minimum element.
9008 // minimum_idx([3, 1, 4, 2]) == 1
9009 // Unsafe! Crashes on an empty sequence.
9010 template <typename Container>
minimum_idx(const Container & xs)9011 typename std::size_t minimum_idx(const Container& xs)
9012 {
9013     return minimum_idx_by(is_less<typename Container::value_type>, xs);
9014 }
9015 
9016 // API search type: minimum_idx_maybe : [a] -> Maybe Int
9017 // fwd bind count: 0
9018 // Return the index of the first minimum element if sequence is not empty.
9019 // minimum_idx_maybe([3, 1, 4, 2]) == Just 1
9020 // minimum_idx_maybe([]) == Nothing
9021 template <typename Container>
minimum_idx_maybe(const Container & xs)9022 maybe<typename std::size_t> minimum_idx_maybe(const Container& xs)
9023 {
9024     if (is_empty(xs))
9025         return {};
9026     else
9027         return minimum_idx(xs);
9028 }
9029 
9030 // API search type: maximum_idx : [a] -> Int
9031 // fwd bind count: 0
9032 // Return the index of the first maximum element.
9033 // maximum_idx([3, 1, 4, 2]) == 2
9034 // Unsafe! Crashes on an empty sequence.
9035 template <typename Container>
maximum_idx(const Container & xs)9036 typename std::size_t maximum_idx(const Container& xs)
9037 {
9038     return maximum_idx_by(is_less<typename Container::value_type>, xs);
9039 }
9040 
9041 // API search type: maximum_idx_maybe : [a] -> Maybe Int
9042 // fwd bind count: 0
9043 // Return the index of the first maximum element if sequence is not empty.
9044 // maximum_idx_maybe([3, 1, 4, 2]) == Just 2
9045 // maximum_imaximum_idx_maybedx([]) == Nothing
9046 template <typename Container>
maximum_idx_maybe(const Container & xs)9047 maybe<typename std::size_t> maximum_idx_maybe(const Container& xs)
9048 {
9049     if (is_empty(xs))
9050         return {};
9051     else
9052         return maximum_idx(xs);
9053 }
9054 
9055 
9056 // API search type: minimum_idx_on : ((a -> b), [a]) -> Int
9057 // fwd bind count: 1
9058 // Return the index of the first minimum element using a transformer.
9059 // minimum_idx_on(length, ["123", "12", "1234", "123"]) -> "1"
9060 // Unsafe! Crashes on an empty sequence.
9061 template <typename F, typename Container>
minimum_idx_on(F f,const Container & xs)9062 std::size_t minimum_idx_on(F f, const Container& xs)
9063 {
9064     using Result = internal::invoke_result_t<F, typename Container::value_type>;
9065     auto transformed = transform_convert<std::vector<std::decay_t<Result>>>(f, xs);
9066     return minimum_idx(transformed);
9067 }
9068 
9069 // API search type: minimum_idx_on_maybe : ((a -> b), [a]) -> Just Int
9070 // fwd bind count: 1
9071 // Return the index of the first minimum element using a transformer
9072 // if sequence is not empty.
9073 // minimum_idx_on_maybe(length, ["123", "12", "1234", "123"]) -> Just "1"
9074 // minimum_idx_on_maybe(length, []) -> Nothing"
9075 template <typename F, typename Container>
minimum_idx_on_maybe(F f,const Container & xs)9076 maybe<typename std::size_t> minimum_idx_on_maybe(F f, const Container& xs)
9077 {
9078     if (is_empty(xs))
9079         return {};
9080     else
9081         return minimum_idx_on(f, xs);
9082 }
9083 
9084 // API search type: maximum_idx_on : ((a -> b), [a]) -> Int
9085 // fwd bind count: 1
9086 // Return the index of the first maximum element using a transformer.
9087 // maximum_idx_on(length, ["123", "12", "1234", "123"]) == "2"
9088 // Unsafe! Crashes on an empty sequence.
9089 template <typename F, typename Container>
maximum_idx_on(F f,const Container & xs)9090 std::size_t maximum_idx_on(F f, const Container& xs)
9091 {
9092     using Result = internal::invoke_result_t<F, typename Container::value_type>;
9093     auto transformed = transform_convert<std::vector<std::decay_t<Result>>>(f, xs);
9094     return maximum_idx(transformed);
9095 }
9096 
9097 // API search type: maximum_idx_on_maybe : ((a -> b), [a]) -> Maybe Int
9098 // fwd bind count: 1
9099 // Return the index of the first maximum element using a transformer
9100 // if sequence is not empty.
9101 // maximum_idx_on_maybe(length, ["123", "12", "1234", "123"]) == Just "2"
9102 // maximum_idx_on_maybe(length, []) == Nothing
9103 template <typename F, typename Container>
maximum_idx_on_maybe(F f,const Container & xs)9104 maybe<typename std::size_t> maximum_idx_on_maybe(F f, const Container& xs)
9105 {
9106     if (is_empty(xs))
9107         return {};
9108     else
9109         return maximum_idx_on(f, xs);
9110 }
9111 
9112 // API search type: minimum_by : (((a, a) -> Bool), [a]) -> a
9113 // fwd bind count: 1
9114 // Return the first minimum element using a less comparator.
9115 // minimum_by(lessLength, ["123", "12", "1234", "123"]) -> "12"
9116 // Unsafe! Crashes on an empty sequence.
9117 template <typename Compare, typename Container>
minimum_by(Compare comp,const Container & xs)9118 typename Container::value_type minimum_by(Compare comp,
9119         const Container& xs)
9120 {
9121     internal::check_compare_for_container<Compare, Container>();
9122     assert(is_not_empty(xs));
9123     return *std::min_element(std::begin(xs), std::end(xs), comp);
9124 }
9125 
9126 // API search type: minimum_by_maybe : (((a, a) -> Bool), [a]) -> a
9127 // fwd bind count: 1
9128 // Return the first minimum element using a less comparator
9129 // if sequence is not empty.
9130 // minimum_by_maybe(lessLength, ["123", "12", "1234", "123"]) -> Just "12"
9131 // minimum_by_maybe(lessLength, []) -> Nothing
9132 template <typename Compare, typename Container>
minimum_by_maybe(Compare comp,const Container & xs)9133 maybe<typename Container::value_type> minimum_by_maybe(Compare comp,
9134         const Container& xs)
9135 {
9136     if (is_empty(xs))
9137         return {};
9138     else
9139         return minimum_by(comp, xs);
9140 }
9141 
9142 // API search type: maximum_by : (((a, a) -> Bool), [a]) -> a
9143 // fwd bind count: 1
9144 // Return the first maximum element using a less comparator.
9145 // maximum_by(lessLength, ["123", "12", "1234", "123"]) == "1234"
9146 // Unsafe! Crashes on an empty sequence.
9147 template <typename Compare, typename Container>
maximum_by(Compare comp,const Container & xs)9148 typename Container::value_type maximum_by(Compare comp,
9149         const Container& xs)
9150 {
9151     internal::check_compare_for_container<Compare, Container>();
9152     assert(is_not_empty(xs));
9153     return *std::max_element(std::begin(xs), std::end(xs), comp);
9154 }
9155 
9156 // API search type: maximum_by_maybe : (((a, a) -> Bool), [a]) -> Maybe a
9157 // fwd bind count: 1
9158 // Return the first maximum element using a less comparator
9159 // if sequence is not empty.
9160 // maximum_by_maybe(lessLength, ["123", "12", "1234", "123"]) == Just "1234"
9161 // maximum_by_maybe(lessLength, []) == Nothing
9162 template <typename Compare, typename Container>
maximum_by_maybe(Compare comp,const Container & xs)9163 maybe<typename Container::value_type> maximum_by_maybe(Compare comp,
9164         const Container& xs)
9165 {
9166     if (is_empty(xs))
9167         return {};
9168     else
9169         return maximum_by(comp, xs);
9170 }
9171 
9172 
9173 // API search type: minimum : [a] -> a
9174 // fwd bind count: 0
9175 // Return the first minimum element.
9176 // minimum([3, 1, 4, 2]) == 1
9177 // Unsafe! Crashes on an empty sequence.
9178 template <typename Container>
minimum(const Container & xs)9179 typename Container::value_type minimum(const Container& xs)
9180 {
9181     return minimum_by(is_less<typename Container::value_type>, xs);
9182 }
9183 
9184 // API search type: minimum_maybe : [a] -> Maybe a
9185 // fwd bind count: 0
9186 // Return the first minimum element if sequence is not empty
9187 // if sequence is not empty.
9188 // minimum_maybe([3, 1, 4, 2]) == Just 1
9189 // minimum_maybe([]) == Nothing
9190 template <typename Container>
minimum_maybe(const Container & xs)9191 maybe<typename Container::value_type> minimum_maybe(const Container& xs)
9192 {
9193     if (is_empty(xs))
9194         return {};
9195     else
9196         return minimum(xs);
9197 }
9198 
9199 // API search type: maximum : [a] -> a
9200 // fwd bind count: 0
9201 // Return the first maximum element.
9202 // maximum([3, 1, 4, 2]) == 4
9203 // Unsafe! Crashes on an empty sequence.
9204 template <typename Container>
maximum(const Container & xs)9205 typename Container::value_type maximum(const Container& xs)
9206 {
9207     return maximum_by(is_less<typename Container::value_type>, xs);
9208 }
9209 
9210 // API search type: maximum_maybe : [a] -> Maybe a
9211 // fwd bind count: 0
9212 // Return the first maximum element if sequence is not empty
9213 // if sequence is not empty.
9214 // maximum_maybe([3, 1, 4, 2]) == Just 4
9215 // maximum_maybe([]) == Nothing
9216 template <typename Container>
maximum_maybe(const Container & xs)9217 maybe<typename Container::value_type> maximum_maybe(const Container& xs)
9218 {
9219     if (is_empty(xs))
9220         return {};
9221     else
9222         return maximum(xs);
9223 }
9224 
9225 
9226 // API search type: minimum_on : ((a -> b), [a]) -> a
9227 // fwd bind count: 1
9228 // Return the first minimum element using a transformer.
9229 // minimum_on(length, ["123", "12", "1234", "123"]) -> "12"
9230 // Unsafe! Crashes on an empty sequence.
9231 template <typename F, typename Container>
minimum_on(F f,const Container & xs)9232 typename Container::value_type minimum_on(F f, const Container& xs)
9233 {
9234     internal::trigger_static_asserts<internal::unary_function_tag, F, typename Container::value_type>();
9235     return elem_at_idx(minimum_idx_on(f, xs), xs);
9236 }
9237 
9238 // API search type: minimum_on_maybe : ((a -> b), [a]) -> Maybe a
9239 // fwd bind count: 1
9240 // Return the first minimum element using a transformer
9241 // if sequence is not empty.
9242 // minimum_on_maybe(length, ["123", "12", "1234", "123"]) -> Just "12"
9243 // minimum_on_maybe(length, []) -> Nothing
9244 template <typename F, typename Container>
minimum_on_maybe(F f,const Container & xs)9245 maybe<typename Container::value_type> minimum_on_maybe(
9246     F f, const Container& xs)
9247 {
9248     if (is_empty(xs))
9249         return {};
9250     else
9251         return minimum_on(f, xs);
9252 }
9253 
9254 // API search type: maximum_on : ((a -> b), [a]) -> a
9255 // fwd bind count: 1
9256 // Return the first maximum element using a transformer.
9257 // maximum_on(length, ["123", "12", "1234", "123"]) == "1234"
9258 // Unsafe! Crashes on an empty sequence.
9259 template <typename F, typename Container>
maximum_on(F f,const Container & xs)9260 typename Container::value_type maximum_on(F f, const Container& xs)
9261 {
9262     internal::trigger_static_asserts<internal::unary_function_tag, F, typename Container::value_type>();
9263     return elem_at_idx(maximum_idx_on(f, xs), xs);
9264 }
9265 
9266 // API search type: maximum_on_maybe : ((a -> b), [a]) -> Maybe a
9267 // fwd bind count: 1
9268 // Return the first maximum element using a transformer
9269 // if sequence is not empty.
9270 // maximum_on_maybe(length, ["123", "12", "1234", "123"]) == Just "1234"
9271 // maximum_on_maybe(length, ["123", "12", "1234", "123"]) == Nothing
9272 template <typename F, typename Container>
maximum_on_maybe(F f,const Container & xs)9273 maybe<typename Container::value_type> maximum_on_maybe(
9274     F f, const Container& xs)
9275 {
9276     if (is_empty(xs))
9277         return {};
9278     else
9279         return maximum_on(f, xs);
9280 }
9281 
9282 // API search type: mean : [a] -> a
9283 // fwd bind count: 0
9284 // mean([1, 4, 4]) == 3
9285 // Also known as average.
9286 // xs must have at least one element.
9287 // Use mean_using_doubles if overflow errors for sum(xs) can occur.
9288 // Unsafe! Crashes on an empty sequence.
9289 template <typename Result, typename Container>
9290 Result mean(const Container& xs)
9291 {
9292     assert(size_of_cont(xs) != 0);
9293     typedef typename Container::value_type T;
9294     return static_cast<Result>(sum(xs) / static_cast<T>(size_of_cont(xs)));
9295 }
9296 
9297 // API search type: mean_obj_div_size_t : [a] -> a
9298 // fwd bind count: 0
9299 // mean_obj_div_size_t([B 1, B 4, B 4]) == B 3
9300 // The provided objects must support division by a std::size_t.
9301 // Unsafe! Crashes on an empty sequence.
9302 // Also Make sure sum(xs) does not overflow.
9303 template <typename Container,
9304     typename T = typename Container::value_type>
mean_obj_div_size_t(const Container & xs)9305 T mean_obj_div_size_t(const Container& xs)
9306 {
9307     assert(size_of_cont(xs) != 0);
9308     return sum(xs) / size_of_cont(xs);
9309 }
9310 
9311 // API search type: mean_obj_div_double : [a] -> a
9312 // fwd bind count: 0
9313 // mean_obj_div_double([B 1, B 4, B 4]) == B 3
9314 // The provided objects must support division by a double.
9315 // Unsafe! Crashes on an empty sequence.
9316 // Also Make sure sum(xs) does not overflow.
9317 template <typename Container,
9318     typename T = typename Container::value_type>
mean_obj_div_double(const Container & xs)9319 T mean_obj_div_double(const Container& xs)
9320 {
9321     assert(size_of_cont(xs) != 0);
9322     return sum(xs) / static_cast<double>(size_of_cont(xs));
9323 }
9324 
9325 // API search type: mean_using_doubles : [a] -> a
9326 // fwd bind count: 0
9327 // mean_using_doubles([1, 4, 4]) == 3
9328 // Converts elements to double before calculating the sum
9329 // to prevent overflows.
9330 // Unsafe! Crashes on an empty sequence.
9331 template <typename Result, typename Container>
9332 Result mean_using_doubles(const Container& xs)
9333 {
9334     assert(size_of_cont(xs) != 0);
9335     auto xs_as_doubles = convert_elems<double>(xs);
9336     auto result_as_double = mean<double>(xs_as_doubles);
9337     if (!std::is_integral<Result>::value)
9338         return static_cast<Result>(result_as_double);
9339     else
9340         return round<double, Result>(result_as_double);
9341 }
9342 
9343 // API search type: median : [a] -> a
9344 // fwd bind count: 0
9345 // median([5, 6, 4, 3, 2, 6, 7, 9, 3]) == 5
9346 // Unsafe! Crashes on an empty sequence.
9347 template <typename Container,
9348         typename Result = typename Container::value_type>
median(const Container & xs)9349 Result median(const Container& xs)
9350 {
9351     assert(is_not_empty(xs));
9352 
9353     if (size_of_cont(xs) == 1)
9354         return static_cast<Result>(xs.front());
9355 
9356     // std::nth_element (instead of sorting)
9357     // would be faster for random-access containers
9358     // but not work at all on other containers like std::list.
9359     auto xsSorted = sort(xs);
9360     if (is_odd(size_of_cont(xsSorted)))
9361     {
9362         auto it = std::begin(xsSorted);
9363         internal::advance_iterator(it, size_of_cont(xsSorted) / 2);
9364         return static_cast<Result>(*it);
9365     }
9366     else
9367     {
9368         auto it1 = std::begin(xsSorted);
9369         internal::advance_iterator(it1, size_of_cont(xsSorted) / 2 - 1);
9370         auto it2 = it1;
9371         ++it2;
9372         return static_cast<Result>(*it1 + *it2) / static_cast<Result>(2);
9373     }
9374 }
9375 
9376 // API search type: all_unique_by_less : (((a, a) -> Bool), [a]) -> Bool
9377 // fwd bind count: 1
9378 // Returns true for empty containers.
9379 // O(n*log(n))
9380 template <typename Container, typename Compare>
all_unique_by_less(Compare comp,const Container & xs)9381 bool all_unique_by_less(Compare comp, const Container& xs)
9382 {
9383     internal::check_compare_for_container<Compare, Container>();
9384     if (size_of_cont(xs) < 2)
9385         return true;
9386     return size_of_cont(unique(sort_by(comp, xs))) == size_of_cont(xs);
9387 }
9388 
9389 // API search type: all_unique_less : [a] -> Bool
9390 // fwd bind count: 0
9391 // Returns true for empty containers.
9392 // O(n*log(n))
9393 template <typename Container>
all_unique_less(const Container & xs)9394 bool all_unique_less(const Container& xs)
9395 {
9396     typedef typename Container::value_type T;
9397     auto comp = std::less<T>();
9398     return all_unique_by_less(comp, xs);
9399 }
9400 
9401 // API search type: is_infix_of : ([a], [a]) -> Bool
9402 // fwd bind count: 1
9403 // is_infix_of("ion", "FunctionalPlus") == true
9404 template <typename Container>
is_infix_of(const Container & token,const Container & xs)9405 bool is_infix_of(const Container& token, const Container& xs)
9406 {
9407     return is_just(find_first_instance_of_token(token, xs));
9408 }
9409 
9410 // API search type: is_subsequence_of : ([a], [a]) -> Bool
9411 // fwd bind count: 1
9412 // is_subsequence_of("Final", "FunctionalPlus") == true
9413 template <typename Container>
is_subsequence_of(const Container & seq,const Container & xs)9414 bool is_subsequence_of(const Container& seq, const Container& xs)
9415 {
9416     if (is_empty(seq))
9417         return true;
9418     if (size_of_cont(seq) > size_of_cont(xs))
9419         return false;
9420     typedef typename Container::value_type T;
9421     auto remaining = convert_container_and_elems<std::list<T>>(seq);
9422     for (const auto& x : xs)
9423     {
9424         if (x == remaining.front())
9425         {
9426             remaining.pop_front();
9427             if (is_empty(remaining))
9428                 return true;
9429         }
9430     }
9431     return false;
9432 }
9433 
9434 // API search type: count_if : ((a -> Bool), [a]) -> Int
9435 // fwd bind count: 1
9436 // count_if(is_even, [1, 2, 3, 5, 7, 8]) == 2
9437 template <typename UnaryPredicate, typename Container>
count_if(UnaryPredicate p,const Container & xs)9438 std::size_t count_if(UnaryPredicate p, const Container& xs)
9439 {
9440     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
9441     return size_of_cont(find_all_idxs_by(p, xs));
9442 }
9443 
9444 // API search type: count : (a, [a]) -> Int
9445 // fwd bind count: 1
9446 // count(2, [1, 2, 3, 5, 7, 2, 2]) == 3
9447 template <typename Container>
count(const typename Container::value_type & x,const Container & xs)9448 std::size_t count
9449         (const typename Container::value_type& x, const Container& xs)
9450 {
9451     return size_of_cont(find_all_idxs_of(x, xs));
9452 }
9453 
9454 // API search type: is_unique_in_by : ((a -> bool), [a]) -> Bool
9455 // fwd bind count: 1
9456 // is_unique_in_by((==2), [1, 2, 3, 5, 7, 2, 2]) == false
9457 // is_unique_in_by((==5), [1, 2, 3, 5, 7, 2, 2]) == true
9458 template <typename UnaryPredicate, typename Container>
is_unique_in_by(UnaryPredicate pred,const Container & xs)9459 bool is_unique_in_by
9460         (UnaryPredicate pred, const Container& xs)
9461 {
9462     std::size_t count = 0;
9463     for (const auto& x : xs)
9464     {
9465         if (internal::invoke(pred, x))
9466         {
9467             ++count;
9468             if (count > 1)
9469             {
9470                 return false;
9471             }
9472         }
9473     }
9474     return true;
9475 }
9476 
9477 // API search type: is_unique_in : (a, [a]) -> Bool
9478 // fwd bind count: 1
9479 // is_unique_in(2, [1, 2, 3, 5, 7, 2, 2]) == false
9480 // is_unique_in(5, [1, 2, 3, 5, 7, 2, 2]) == true
9481 template <typename Container>
is_unique_in(const typename Container::value_type & x,const Container & xs)9482 bool is_unique_in
9483         (const typename Container::value_type& x, const Container& xs)
9484 {
9485     return is_unique_in_by(is_equal_to(x), xs);
9486 }
9487 
9488 // API search type: is_permutation_of : ([a], [a]) -> Bool
9489 // fwd bind count: 1
9490 // Checks if one container is a permuation of the other one.
9491 // is_permutation_of([2,3,1], [1,2,3]) == true
9492 // O(log(n))
9493 template <typename Container>
is_permutation_of(const Container & xs,const Container & ys)9494 bool is_permutation_of(const Container& xs, const Container& ys)
9495 {
9496     return size_of_cont(xs) == size_of_cont(ys) &&
9497         sort(xs) == sort(ys);
9498 }
9499 
9500 // API search type: fill_pigeonholes_to : (Int, [Int]) -> [Int]
9501 // fwd bind count: 1
9502 // Returns a list containing the count for every element in xs
9503 // with the value corresponding to the index in the result list.
9504 // fill_pigeonholes_to(5, [0,1,3,1]) == [1,2,0,1,0]
9505 // fill_pigeonholes_to(3, [0,1,3,1]) == [1,2,0]
9506 template <typename ContainerIn,
9507     typename ContainerOut = std::vector<std::size_t>,
9508     typename T = typename ContainerIn::value_type>
9509 ContainerOut fill_pigeonholes_to(std::size_t idx_end, const ContainerIn& xs)
9510 {
9511     static_assert(std::is_integral<T>::value,
9512         "Type must be integral.");
9513 
9514     if (is_empty(xs))
9515         return {};
9516 
9517     ContainerOut result(idx_end, 0);
9518     for (const auto& x : xs)
9519     {
9520         if (x >= 0)
9521         {
9522             const auto idx = static_cast<std::size_t>(x);
9523             if (idx < result.size())
9524             {
9525                 ++result[idx];
9526             }
9527         }
9528     }
9529     return result;
9530 }
9531 
9532 // API search type: fill_pigeonholes : [Int] -> [Int]
9533 // fwd bind count: 0
9534 // Returns a list containing the count for every element in xs
9535 // with the value corresponding to the index in the result list.
9536 // fill_pigeonholes([0,1,3,1]) == [1,2,0,1]
9537 template <typename ContainerIn,
9538     typename ContainerOut = std::vector<std::size_t>,
9539     typename T = typename ContainerIn::value_type>
9540 ContainerOut fill_pigeonholes(const ContainerIn& xs)
9541 {
9542     static_assert(std::is_integral<T>::value,
9543         "Type must be integral.");
9544 
9545     if (is_empty(xs))
9546         return {};
9547 
9548     return(fill_pigeonholes_to<ContainerIn, ContainerOut>(
9549         maximum(xs) + 1, xs));
9550 }
9551 
9552 // API search type: fill_pigeonholes_bool_to : (Int, [Int]) -> [Int]
9553 // fwd bind count: 1
9554 // Returns a list telling if the element corresponding to the index
9555 // is present in xs.
9556 // fill_pigeonholes_bool_to(5, [0,1,3,1]) == [1,1,0,1,0]
9557 // fill_pigeonholes_bool_to(3, [0,1,3,1]) == [1,1,0]
9558 template <typename ContainerIn,
9559     typename ContainerOut = std::vector<std::uint8_t>,
9560     typename T = typename ContainerIn::value_type>
9561 ContainerOut fill_pigeonholes_bool_to(std::size_t idx_end, const ContainerIn& xs)
9562 {
9563     static_assert(std::is_integral<T>::value,
9564         "Type must be integral.");
9565 
9566     if (is_empty(xs))
9567         return {};
9568 
9569     ContainerOut result(idx_end, 0);
9570     for (const auto& x : xs)
9571     {
9572         if (x >= 0)
9573         {
9574             const auto idx = static_cast<std::size_t>(x);
9575             if (idx < result.size())
9576             {
9577                 result[idx] = 1;
9578             }
9579         }
9580     }
9581     return result;
9582 }
9583 
9584 // API search type: fill_pigeonholes_bool : [Int] -> [Int]
9585 // fwd bind count: 0
9586 // Returns a list telling if the element corresponding to the index
9587 // is present in xs.
9588 // fill_pigeonholes_bool([0,1,3,1]) == [1,2,0,1]
9589 template <typename ContainerIn,
9590     typename ContainerOut = std::vector<std::uint8_t>,
9591     typename T = typename ContainerIn::value_type>
9592 ContainerOut fill_pigeonholes_bool(const ContainerIn& xs)
9593 {
9594     static_assert(std::is_integral<T>::value,
9595         "Type must be integral.");
9596 
9597     if (is_empty(xs))
9598         return {};
9599 
9600     return(fill_pigeonholes_bool_to<ContainerIn, ContainerOut>(
9601         maximum(xs) + 1, xs));
9602 }
9603 
9604 // API search type: present_in_all : [[a]] -> [a]
9605 // fwd bind count: 0
9606 // Returns a list containing only the elements present in all sublists of xs.
9607 // Also known as gemstones.
9608 // present_in_all([[4,1,2], [5,2,1], [2,4,1]]) == [1,2]
9609 template <typename ContainerIn,
9610     typename SubContainerIn = typename ContainerIn::value_type,
9611     typename T = typename SubContainerIn::value_type,
9612     typename ContainerOut = std::vector<T>>
present_in_all(const ContainerIn & xs)9613 ContainerOut present_in_all(const ContainerIn& xs)
9614 {
9615     return convert_container<ContainerOut>(
9616         fplus::sets_intersection(
9617             transform(
9618                 convert_container<std::set<T>, SubContainerIn>,
9619                 xs)));
9620 }
9621 
9622 } // namespace fplus
9623 
9624 //
9625 // extrapolate.hpp
9626 //
9627 
9628 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
9629 // https://github.com/Dobiasd/FunctionalPlus
9630 // Distributed under the Boost Software License, Version 1.0.
9631 // (See accompanying file LICENSE_1_0.txt or copy at
9632 //  http://www.boost.org/LICENSE_1_0.txt)
9633 
9634 
9635 
9636 namespace fplus
9637 {
9638 
9639 // API search type: elem_at_idx_or_nothing : (Int, [a]) -> Maybe a
9640 // fwd bind count: 1
9641 // Return nth element of a sequence.
9642 // Returns nothing if index is outside of xs.
9643 template <typename Container,
9644     typename T = typename Container::value_type>
elem_at_idx_or_nothing(signed int idx,const Container & xs)9645 maybe<T> elem_at_idx_or_nothing(signed int idx, const Container& xs)
9646 {
9647     if (idx < 0 || idx >= static_cast<signed int>(size_of_cont(xs)))
9648     {
9649         return {};
9650     }
9651     auto it = std::begin(xs);
9652     internal::advance_iterator(it, static_cast<std::size_t>(idx));
9653     return *it;
9654 }
9655 
9656 // API search type: elem_at_idx_or_constant : (a, Int, [a]) -> a
9657 // fwd bind count: 2
9658 // Return nth element of a sequence.
9659 // Interpolate outside of sequence with a constant value.
9660 // iiiiii|abcdefgh|iiiiiii
9661 template <typename Container,
9662     typename T = typename Container::value_type>
elem_at_idx_or_constant(const T & c,signed int idx,const Container & xs)9663 T elem_at_idx_or_constant(const T& c, signed int idx, const Container& xs)
9664 {
9665     if (idx < 0 || idx >= static_cast<signed int>(size_of_cont(xs)))
9666     {
9667         return c;
9668     }
9669     auto it = std::begin(xs);
9670     internal::advance_iterator(it, static_cast<std::size_t>(idx));
9671     return *it;
9672 }
9673 
9674 // API search type: elem_at_idx_or_replicate : (Int, [a]) -> a
9675 // fwd bind count: 1
9676 // Return nth element of a sequence.
9677 // Interpolate outside of sequence by replicating the nearest inside value.
9678 // aaaaaa|abcdefgh|hhhhhhh
9679 // xs must be non-empty.
9680 template <typename Container,
9681     typename T = typename Container::value_type>
elem_at_idx_or_replicate(signed int idx,const Container & xs)9682 T elem_at_idx_or_replicate(signed int idx, const Container& xs)
9683 {
9684     assert(is_not_empty(xs));
9685     if (idx < 0)
9686     {
9687         return xs.front();
9688     }
9689     if (idx >= static_cast<signed int>(size_of_cont(xs)))
9690     {
9691         return xs.back();
9692     }
9693     auto it = std::begin(xs);
9694     internal::advance_iterator(it, static_cast<std::size_t>(idx));
9695     return *it;
9696 }
9697 
9698 // API search type: elem_at_idx_or_wrap : (Int, [a]) -> a
9699 // fwd bind count: 1
9700 // Return nth element of a sequence.
9701 // Interpolate outside of sequence by replicating the sequence.
9702 // For cyclic element access.
9703 // cdefgh|abcdefgh|abcdefg
9704 // xs must be non-empty.
9705 template <typename Container,
9706     typename T = typename Container::value_type>
elem_at_idx_or_wrap(signed int idx,const Container & xs)9707 T elem_at_idx_or_wrap(signed int idx, const Container& xs)
9708 {
9709     assert(is_not_empty(xs));
9710     const signed int cont_size = static_cast<signed int>(size_of_cont(xs));
9711     if (idx < 0)
9712         idx = cont_size - (std::abs(idx) % cont_size);
9713     else
9714         idx = idx % cont_size;
9715     auto it = std::begin(xs);
9716     internal::advance_iterator(it, static_cast<std::size_t>(idx));
9717     return *it;
9718 }
9719 
9720 // API search type: extrapolate_replicate : (Int, Int, [a]) -> [a]
9721 // fwd bind count: 2
9722 // Extrapolate a sequence by replicating the border values.
9723 // count_begin determines the number of elements to be prepended.
9724 // count_end determines the number of elements to be appended.
9725 // aaaaaa|abcdefgh|hhhhhhh
9726 // xs must be non-empty.
9727 template <typename Container,
9728     typename T = typename Container::value_type>
9729 Container extrapolate_replicate(std::size_t count_begin, std::size_t count_end,
9730         const Container& xs)
9731 {
9732     assert(is_not_empty(xs));
9733     Container ys;
9734     const auto xs_size = size_of_cont(xs);
9735     internal::prepare_container(ys, xs_size + count_begin + count_end);
9736     auto it = internal::get_back_inserter<Container>(ys);
9737     const signed int idx_end = static_cast<signed int>(xs_size + count_end);
9738     const signed int idx_start = -static_cast<signed int>(count_begin);
9739     for (signed int idx = idx_start; idx < idx_end; ++idx)
9740     {
9741         *it = elem_at_idx_or_replicate(idx, xs);
9742     }
9743     return ys;
9744 }
9745 
9746 // API search type: extrapolate_wrap : (Int, Int, [a]) -> [a]
9747 // fwd bind count: 2
9748 // Extrapolate a sequence by accessing the elements in cyclic fashion.
9749 // count_begin determines the number of elements to be prepended.
9750 // count_end determines the number of elements to be appended.
9751 // cdefgh|abcdefgh|abcdefg
9752 // xs must be non-empty.
9753 template <typename Container,
9754     typename T = typename Container::value_type>
9755 Container extrapolate_wrap(std::size_t count_begin, std::size_t count_end,
9756         const Container& xs)
9757 {
9758     assert(is_not_empty(xs));
9759     Container ys;
9760     const auto xs_size = size_of_cont(xs);
9761     internal::prepare_container(ys, xs_size + count_begin + count_end);
9762     auto it = internal::get_back_inserter<Container>(ys);
9763     const signed int idx_end = static_cast<signed int>(xs_size + count_end);
9764     const signed int idx_start = -static_cast<signed int>(count_begin);
9765     for (signed int idx = idx_start; idx < idx_end; ++idx)
9766     {
9767         *it = elem_at_idx_or_wrap(idx, xs);
9768     }
9769     return ys;
9770 }
9771 
9772 } // namespace fplus
9773 
9774 //
9775 // interpolate.hpp
9776 //
9777 
9778 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
9779 // https://github.com/Dobiasd/FunctionalPlus
9780 // Distributed under the Boost Software License, Version 1.0.
9781 // (See accompanying file LICENSE_1_0.txt or copy at
9782 //  http://www.boost.org/LICENSE_1_0.txt)
9783 
9784 
9785 
9786 #include <cmath>
9787 
9788 namespace fplus
9789 {
9790 
9791 // API search type: elem_at_float_idx : (Float, [a]) -> a
9792 // fwd bind count: 1
9793 // Interpolates linearly between elements.
9794 // xs must be non-empty.
9795 template <typename Container,
9796     typename T = typename Container::value_type>
elem_at_float_idx(double idx,const Container & xs)9797 T elem_at_float_idx(double idx, const Container& xs)
9798 {
9799     assert(is_not_empty(xs));
9800     if (idx <= 0.0)
9801     {
9802         return xs.front();
9803     }
9804     std::size_t idx_floor = static_cast<std::size_t>(floor(idx));
9805     std::size_t idx_ceil = static_cast<std::size_t>(ceil(idx));
9806     if (idx_ceil >= size_of_cont(xs))
9807     {
9808         return xs.back();
9809     }
9810     double idx_floor_float = static_cast<double>(idx_floor);
9811     double idx_ceil_float = static_cast<double>(idx_ceil);
9812     double weight_floor = idx_ceil_float - idx;
9813     double weight_ceil = idx - idx_floor_float;
9814     return
9815         (weight_floor * elem_at_idx(idx_floor, xs) +
9816             weight_ceil * elem_at_idx(idx_ceil, xs));
9817 }
9818 
9819 } // namespace fplus
9820 
9821 //
9822 // maps.hpp
9823 //
9824 
9825 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
9826 // https://github.com/Dobiasd/FunctionalPlus
9827 // Distributed under the Boost Software License, Version 1.0.
9828 // (See accompanying file LICENSE_1_0.txt or copy at
9829 //  http://www.boost.org/LICENSE_1_0.txt)
9830 
9831 
9832 
9833 
9834 #include <map>
9835 #include <unordered_map>
9836 
9837 namespace fplus
9838 {
9839 
9840 // API search type: pairs_to_map : [(key, val)] -> Map key val
9841 // fwd bind count: 0
9842 // Converts a Container of pairs (key, value) into a dictionary.
9843 template <typename MapOut, typename ContainerIn>
9844 MapOut pairs_to_map(const ContainerIn& pairs)
9845 {
9846     return convert_container_and_elems<MapOut>(pairs);
9847 }
9848 
9849 // API search type: pairs_to_map_grouped : [(key, val)] -> Map key [val]
9850 // fwd bind count: 0
9851 // Convert a list of key-value pairs to a dictionary
9852 // while pushing values having the same key into a vector.
9853 // pairs_to_map_grouped([("a", 1), ("a", 2), ("b", 6), ("a", 4)])
9854 //     -> {"a": [1, 2, 4], "b": [6]}
9855 template <typename ContainerIn,
9856     typename Key = typename ContainerIn::value_type::first_type,
9857     typename SingleValue = typename ContainerIn::value_type::second_type,
9858     typename MapOut = std::map<Key, std::vector<SingleValue>>>
pairs_to_map_grouped(const ContainerIn & pairs)9859 MapOut pairs_to_map_grouped(const ContainerIn& pairs)
9860 {
9861     MapOut result;
9862     for (const auto& p : pairs)
9863     {
9864         result[p.first].push_back(p.second);
9865     }
9866     return result;
9867 }
9868 
9869 // API search type: pairs_to_unordered_map_grouped : [(key, val)] -> Map key [val]
9870 // fwd bind count: 0
9871 // Convert a list of key-value pairs to a dictionary
9872 // while pushing values having the same key into a vector.
9873 // pairs_to_unordered_map_grouped([("a", 1), ("a", 2), ("b", 6), ("a", 4)])
9874 //     -> {"a": [1, 2, 4], "b": [6]}
9875 template <typename ContainerIn,
9876     typename Key = typename ContainerIn::value_type::first_type,
9877     typename SingleValue = typename ContainerIn::value_type::second_type,
9878     typename MapOut = std::unordered_map<Key, std::vector<SingleValue>>>
pairs_to_unordered_map_grouped(const ContainerIn & pairs)9879 MapOut pairs_to_unordered_map_grouped(const ContainerIn& pairs)
9880 {
9881     MapOut result;
9882     for (const auto& p : pairs)
9883     {
9884         result[p.first].push_back(p.second);
9885     }
9886     return result;
9887 }
9888 
9889 // API search type: map_to_pairs : Map key val -> [(key, val)]
9890 // fwd bind count: 0
9891 // Converts a dictionary into a Container of pairs (key, value).
9892 template <typename MapType,
9893     typename MapPair = typename MapType::value_type,
9894     typename Key = typename std::remove_const<typename MapPair::first_type>::type,
9895     typename Val = typename std::remove_const<typename MapPair::second_type>::type,
9896     typename OutPair = std::pair<Key, Val>,
9897     typename ContainerOut = std::vector<OutPair>>
map_to_pairs(const MapType & dict)9898 ContainerOut map_to_pairs(const MapType& dict)
9899 {
9900     return convert_container_and_elems<ContainerOut>(dict);
9901 }
9902 
9903 // API search type: transform_map_values : ((old_val -> new_val), Map key old_val) -> Map key new_val
9904 // fwd bind count: 1
9905 // Manipulate the values in a dictionary, keeping the key-value relationship.
9906 // transform_map_values((*2), {0: 2, 1: 3}) == {0: 4, 1: 6}
9907 template <typename F, typename MapIn>
transform_map_values(F f,const MapIn & map)9908 auto transform_map_values(F f, const MapIn& map)
9909 {
9910     using MapInPair = typename MapIn::value_type;
9911     using Key = std::remove_const_t<typename MapInPair::first_type>;
9912     using InVal = std::remove_const_t<typename MapInPair::second_type>;
9913     using OutVal = std::decay_t<internal::invoke_result_t<F, InVal>>;
9914     using MapOut = typename internal::SameMapTypeNewTypes<MapIn, Key, OutVal>::type;
9915 
9916     return pairs_to_map<MapOut>(
9917         transform(
9918             bind_1st_of_2(transform_snd<Key, InVal, F>, f),
9919             map_to_pairs(map)));
9920 }
9921 
9922 // API search type: map_union_with : (((val, val) -> val), Map key val, Map key val) -> Map key val
9923 // fwd bind count: 2
9924 // Combine two dictionaries using a binary function for the values.
9925 // map_union_with((++), {0: a, 1: b}, {0: c, 2: d}) == {0: ac, 1: b, 2: d}
9926 template <typename F, typename MapIn>
map_union_with(F f,const MapIn & dict1,const MapIn & dict2)9927 auto map_union_with(F f, const MapIn& dict1, const MapIn& dict2)
9928 {
9929     const auto both = append(map_to_pairs(dict1), map_to_pairs(dict2));
9930     using Key = typename decltype(both)::value_type::first_type;
9931     using SingleValue = typename decltype(both)::value_type::second_type;
9932     auto full_map = pairs_to_map_grouped<decltype(both), Key, SingleValue,
9933             typename internal::SameMapTypeNewTypes<MapIn, Key, std::vector<SingleValue>>::type>(both);
9934     const auto group_f = [f](const auto& vals)
9935     {
9936         return fold_left_1(f, vals);
9937     };
9938     return transform_map_values(group_f, full_map);
9939 }
9940 
9941 // API search type: map_union : (Map key val, Map key val) -> Map key val
9942 // fwd bind count: 1
9943 // Combine two dictionaries keeping the value of the first map
9944 // in case of key collisions.
9945 // map_union({0: a, 1: b}, {0: c, 2: d}) == {0: a, 1: b, 2: d}
9946 template <typename MapType>
map_union(const MapType & dict1,const MapType & dict2)9947 MapType map_union(const MapType& dict1, const MapType& dict2)
9948 {
9949     using Value = typename MapType::value_type::second_type;
9950 
9951     const auto get_first = [](const Value& a, const Value&) -> Value
9952     {
9953         return a;
9954     };
9955     return map_union_with(get_first, dict1, dict2);
9956 }
9957 
9958 // API search type: map_grouped_to_pairs : Map key [val] -> [(key, val)]
9959 // fwd bind count: 0
9960 // Convert a dictionary with sequence values to a list of key-value pairs.
9961 // Inverse operation of pairs_to_map_grouped.
9962 // map_grouped_to_pairs({"a": [1, 2, 4], "b": [6]})
9963 //     -> [("a", 1), ("a", 2), ("a", 4), ("b", 6)]
9964 template<typename MapType>
map_grouped_to_pairs(const MapType & dict)9965 auto map_grouped_to_pairs(const MapType &dict)
9966 {
9967     using Key = typename MapType::key_type;
9968     using Group = typename MapType::mapped_type;
9969 
9970     auto fn = [](const auto &pair)
9971     {
9972         const auto f = zip_repeat<std::vector<Key>, Group>;
9973         return apply_to_pair(f, transform_fst(singleton_seq < Key > , pair));
9974     };
9975     return concat(transform(fn, map_to_pairs(dict)));
9976 }
9977 
9978 // API search type: get_map_keys : Map key val -> [key]
9979 // fwd bind count: 0
9980 // Returns all keys used in a map.
9981 template <typename MapType,
9982     typename ContainerOut =
9983         std::vector<typename std::remove_const<typename MapType::key_type>::type>>
get_map_keys(const MapType & dict)9984 ContainerOut get_map_keys(const MapType& dict)
9985 {
9986     auto pairs = map_to_pairs(dict);
9987     typedef typename decltype(pairs)::value_type::first_type FirstType;
9988     typedef typename decltype(pairs)::value_type::second_type SecondType;
9989     return transform_convert<ContainerOut>(
9990         fst<FirstType, SecondType>, map_to_pairs(dict));
9991 }
9992 
9993 // API search type: get_map_values : Map key val -> [val]
9994 // fwd bind count: 0
9995 // Returns all values present in a map.
9996 template <typename MapType,
9997     typename ContainerOut =
9998         std::vector<typename std::remove_const<typename MapType::mapped_type>::type>>
get_map_values(const MapType & dict)9999 ContainerOut get_map_values(const MapType& dict)
10000 {
10001     auto pairs = map_to_pairs(dict);
10002     typedef typename decltype(pairs)::value_type::first_type FirstType;
10003     typedef typename decltype(pairs)::value_type::second_type SecondType;
10004     return transform_convert<ContainerOut>(
10005         snd<FirstType, SecondType>, map_to_pairs(dict));
10006 }
10007 
10008 // API search type: swap_keys_and_values : Map a b -> Map b a
10009 // fwd bind count: 0
10010 // Swaps keys and Values of a dict:
10011 // swap_keys_and_values({1: "a", 2: "b"}) == {"a": 1, "b": 2}
10012 template <typename MapIn,
10013     typename MapInPair = typename MapIn::value_type,
10014     typename InKey = typename MapInPair::first_type,
10015     typename InVal = typename MapInPair::second_type,
10016     typename OutKey = InVal,
10017     typename OutVal = typename std::remove_const<InKey>::type,
10018     typename MapOut = typename internal::SameMapTypeNewTypes<MapIn, OutKey, OutVal>::type>
swap_keys_and_values(const MapIn & dict)10019 MapOut swap_keys_and_values(const MapIn& dict)
10020 {
10021     auto inAsPairs = map_to_pairs(dict);
10022     auto outAsPairs = transform(swap_pair_elems<InKey, InVal>, inAsPairs);
10023     return pairs_to_map<MapOut>(outAsPairs);
10024 }
10025 
10026 // API search type: create_map : ([key], [val]) -> Map key val
10027 // fwd bind count: 1
10028 // Zip a sequence of keys with a sequence of values to obtain a dictionary.
10029 // create_map([1,2,3], ["one", "two"]) == {1: "one", 2: "two"}
10030 template <typename ContainerIn1, typename ContainerIn2,
10031     typename Key = typename std::remove_const<typename ContainerIn1::value_type>::type,
10032     typename Val = typename std::remove_const<typename ContainerIn2::value_type>::type,
10033     typename MapOut = std::map<Key, Val>>
create_map(const ContainerIn1 & keys,const ContainerIn2 & values)10034 MapOut create_map(const ContainerIn1& keys, const ContainerIn2& values)
10035 {
10036     auto pairs = zip(keys, values);
10037     return pairs_to_map<MapOut>(pairs);
10038 }
10039 
10040 // API search type: create_map_with : ((key -> val), [key]) -> Map key val
10041 // fwd bind count: 1
10042 // Take a list of keys and create a dictionary
10043 // generating the values by applying f to each key.
10044 // create_map_with(show, [1,2]) == {1: "1", 2: "2"}
10045 template <typename ContainerIn, typename F>
create_map_with(F f,const ContainerIn & keys)10046 auto create_map_with(F f, const ContainerIn& keys)
10047 {
10048     return create_map(keys, transform(f, keys));
10049 }
10050 
10051 // API search type: create_map_grouped : ((val -> key), [val]) -> Map key val
10052 // fwd bind count: 1
10053 // Take a list of values and create a grouped dictionary
10054 // generating the keys by applying f to each key.
10055 // create_map_grouped(length, ["one", "three", "two"]) == {3: ["one", "two"], 5: ["three"]}
10056 // Also known as group_by
10057 template <typename ContainerIn, typename F>
create_map_grouped(F f,const ContainerIn & values)10058 auto create_map_grouped(F f, const ContainerIn& values)
10059 {
10060     return pairs_to_map_grouped(zip(transform(f, values), values));
10061 }
10062 
10063 // API search type: create_unordered_map : ([key], [val]) -> Map key val
10064 // fwd bind count: 1
10065 // Zip a sequence of keys with a sequence of values to obtain a dictionary.
10066 // create_unordered_map([1,2,3], ["one", "two"]) == {1: "one", 2: "two"}
10067 template <typename ContainerIn1, typename ContainerIn2,
10068     typename Key = typename std::remove_const<typename ContainerIn1::value_type>::type,
10069     typename Val = typename std::remove_const<typename ContainerIn2::value_type>::type,
10070     typename MapOut = std::unordered_map<Key, Val >>
create_unordered_map(const ContainerIn1 & keys,const ContainerIn2 & values)10071 MapOut create_unordered_map(
10072     const ContainerIn1& keys,
10073     const ContainerIn2& values)
10074 {
10075     auto pairs = zip(keys, values);
10076     return pairs_to_map<MapOut>(pairs);
10077 }
10078 
10079 // API search type: create_unordered_map_with : ((key -> val), [key]) -> Map key val
10080 // fwd bind count: 1
10081 // Take a list of keys and create a dictionary
10082 // generating the values by applying f to each key.
10083 // create_unordered_map_with(show, [1,2]) == {1: "1", 2: "2"}
10084 template <typename ContainerIn, typename F>
create_unordered_map_with(F f,const ContainerIn & keys)10085 auto create_unordered_map_with(F f, const ContainerIn& keys)
10086 {
10087     return create_unordered_map(keys, transform(f, keys));
10088 }
10089 
10090 // API search type: create_unordered_map_grouped : ((val -> key), [val]) -> Map key val
10091 // fwd bind count: 1
10092 // Take a list of values and create a grouped dictionary
10093 // generating the keys by applying f to each key.
10094 // create_unordered_map_grouped(length, ["one", "three", "two"]) == {3: ["one", "two"], 5: ["three"]}
10095 // Also known as group_by
10096 template <typename ContainerIn, typename F>
create_unordered_map_grouped(F f,const ContainerIn & values)10097 auto create_unordered_map_grouped(F f, const ContainerIn& values)
10098 {
10099     return pairs_to_unordered_map_grouped(zip(transform(f, values), values));
10100 }
10101 
10102 // API search type: get_from_map : (Map key val, key) -> Maybe val
10103 // fwd bind count: 1
10104 // Returns just the value of a key if key is present.
10105 // Otherwise returns nothing.
10106 template <typename MapType,
10107     typename Key = typename MapType::key_type,
10108     typename Val = typename MapType::mapped_type>
get_from_map(const MapType & map,const Key & key)10109 maybe<Val> get_from_map(const MapType& map, const Key& key)
10110 {
10111     auto it = map.find(key);
10112     if (it == std::end(map))
10113         return nothing<Val>();
10114     return just(it->second);
10115 }
10116 
10117 // API search type: get_from_map_unsafe : (Map key val, key) -> val
10118 // fwd bind count: 1
10119 // Returns the value of a key if key is present.
10120 // Crashes otherwise.
10121 template <typename MapType,
10122     typename Key = typename MapType::key_type,
10123     typename Val = typename MapType::mapped_type>
get_from_map_unsafe(const MapType & map,const Key & key)10124 Val get_from_map_unsafe(const MapType& map, const Key& key)
10125 {
10126     return unsafe_get_just(get_from_map(map, key));
10127 }
10128 
10129 // API search type: get_from_map_with_def : (Map key val, val, key) -> val
10130 // fwd bind count: 2
10131 // Returns the value of a key if key is present.
10132 // Otherwise returns the provided default.
10133 // Also known as prop_or.
10134 template <typename MapType,
10135     typename Key = typename MapType::key_type,
10136     typename Val = typename MapType::mapped_type>
get_from_map_with_def(const MapType & map,const Val & defVal,const Key & key)10137 Val get_from_map_with_def(const MapType& map, const Val& defVal,
10138     const Key& key)
10139 {
10140     return just_with_default(defVal, get_from_map(map, key));
10141 }
10142 
10143 // API search type: get_first_from_map : (Map key val, [key]) -> Maybe val
10144 // fwd bind count: 1
10145 // Returns just the value of the first key present.
10146 // Otherwise returns nothing.
10147 template <typename MapType,
10148     typename KeysContainer,
10149     typename Key = typename MapType::key_type,
10150     typename Val = typename MapType::mapped_type>
get_first_from_map(const MapType & map,const KeysContainer & keys)10151 maybe<Val> get_first_from_map(const MapType& map, const KeysContainer& keys)
10152 {
10153     static_assert(std::is_same<typename KeysContainer::value_type, Key>::value,
10154         "Key type does not match.");
10155     for (const auto& key: keys)
10156     {
10157         auto it = map.find(key);
10158         if (it != std::end(map))
10159             return just(it->second);
10160     }
10161     return nothing<Val>();
10162 }
10163 
10164 // API search type: get_first_from_map_unsafe : (Map key val, [key]) -> val
10165 // fwd bind count: 1
10166 // Returns the value of the first key present.
10167 // Crashes otherwise.
10168 template <typename MapType,
10169     typename KeysContainer,
10170     typename Key = typename MapType::key_type,
10171     typename Val = typename MapType::mapped_type>
get_first_from_map_unsafe(const MapType & map,const KeysContainer & keys)10172 Val get_first_from_map_unsafe(const MapType& map, const KeysContainer& keys)
10173 {
10174     return unsafe_get_just(get_first_from_map(map, keys));
10175 }
10176 
10177 // API search type: get_first_from_map_with_def : (Map key val, val, [key]) -> val
10178 // fwd bind count: 2
10179 // Returns the value of the first key present.
10180 // Otherwise returns the provided default.
10181 template <typename MapType,
10182     typename KeysContainer,
10183     typename Key = typename MapType::key_type,
10184     typename Val = typename MapType::mapped_type>
get_first_from_map_with_def(const MapType & map,const Val & defVal,const KeysContainer & keys)10185 Val get_first_from_map_with_def(const MapType& map, const Val& defVal,
10186     const KeysContainer& keys)
10187 {
10188     return just_with_default(defVal, get_first_from_map(map, keys));
10189 }
10190 
10191 // API search type: map_contains : (Map key val, key) -> Bool
10192 // fwd bind count: 1
10193 // Checks if a map contains a key.
10194 template <typename MapType, typename Key = typename MapType::key_type>
map_contains(const MapType & map,const Key & key)10195 bool map_contains(const MapType& map, const Key& key)
10196 {
10197     auto it = map.find(key);
10198     return it != std::end(map);
10199 }
10200 
10201 // API search type: map_keep_if : ((key -> Bool), Map key val) -> Map key val
10202 // fwd bind count: 1
10203 // Filters the map by keys.
10204 // map_keep_if(is_upper_case, {a: 1, b: 2, A: 3, C: 4}) == {A: 3, C: 4}
10205 // Also known as pick_by.
10206 template <typename MapType, typename Pred>
10207 MapType map_keep_if(Pred pred, const MapType& map)
10208 {
10209     MapType result;
10210     for (const auto& key_and_value : map)
10211     {
10212         if (internal::invoke(pred, key_and_value.first))
10213         {
10214             result.insert(key_and_value);
10215         }
10216     }
10217     return result;
10218 }
10219 
10220 // API search type: map_drop_if : ((key -> Bool), Map key val) -> Map key val
10221 // fwd bind count: 1
10222 // Filters the map by keys.
10223 // map_drop_if(is_lower_case, {a: 1, b: 2, A: 3, C: 4}) == {A: 3, C: 4}
10224 // Inverse of map_keep_if.
10225 template <typename MapType, typename Pred>
10226 MapType map_drop_if(Pred pred, const MapType& map)
10227 {
10228     return map_keep_if(logical_not(pred), map);
10229 }
10230 
10231 // API search type: map_keep : ([key], Map key val) -> Map key val
10232 // fwd bind count: 1
10233 // Keeps only the pairs of the map found in the key list.
10234 // map_keep([a, d], {a: 1, b: 2, c: 3, d: 4}) == {a: 1, d: 4}
10235 // map_keep([a, e, f], {a: 1, b: 2, c: 3, d: 4}) == {a: 1}
10236 // Also known as pick.
10237 template <typename MapType, typename KeyContainer>
10238 MapType map_keep(const KeyContainer& keys, const MapType& map)
10239 {
10240     static_assert(std::is_same<
10241         typename KeyContainer::value_type,
10242         typename MapType::key_type>::value,
10243         "Key types do not match.");
10244     return map_keep_if(bind_2nd_of_2(is_elem_of<KeyContainer>, keys), map);
10245 }
10246 
10247 // API search type: map_drop : ([key], Map key val) -> Map key val
10248 // fwd bind count: 1
10249 // Keeps only the pairs of the map not found in the key list.
10250 // Inverse of map_keep.
10251 // map_drop([b, c], {a: 1, b: 2, c: 3, d: 4}); == {a: 1, d: 4}
10252 template <typename MapType, typename KeyContainer>
10253 MapType map_drop(const KeyContainer& keys, const MapType& map)
10254 {
10255     static_assert(std::is_same<
10256         typename KeyContainer::value_type,
10257         typename MapType::key_type>::value,
10258         "Key types do not match.");
10259     return map_drop_if(bind_2nd_of_2(is_elem_of<KeyContainer>, keys), map);
10260 }
10261 
10262 // API search type: map_keep_if_value : ((val -> Bool), Map key val) -> Map key val
10263 // fwd bind count: 1
10264 // Filters the map by values.
10265 // map_keep_if_value(is_upper_case, {1: a, 2: b, 3: A, 4: C}) == {3: A, 4: C}
10266 // Also known as filter_values.
10267 template <typename MapType, typename Pred>
10268 MapType map_keep_if_value(Pred pred, const MapType& map)
10269 {
10270     MapType result;
10271     for (const auto& key_and_value : map)
10272     {
10273         if (internal::invoke(pred, key_and_value.second))
10274         {
10275             result.insert(key_and_value);
10276         }
10277     }
10278     return result;
10279 }
10280 
10281 // API search type: map_drop_if_value : ((value -> Bool), Map key val) -> Map key val
10282 // fwd bind count: 1
10283 // Filters the map by values.
10284 // map_drop_if_value(is_lower_case, {1: a, 2: b, 3: A, 4: C}) == {3: A, 4: C}
10285 // Inverse of map_keep_if_value.
10286 template <typename MapType, typename Pred>
10287 MapType map_drop_if_value(Pred pred, const MapType& map)
10288 {
10289     return map_keep_if_value(logical_not(pred), map);
10290 }
10291 
10292 // API search type: map_keep_values : ([value], Map key val) -> Map key val
10293 // fwd bind count: 1
10294 // Keeps only the pairs of the map found in the value list.
10295 // map_keep_values([1, 4], {a: 1, b: 2, c: 3, d: 4}) == {a: 1, d: 4}
10296 // map_keep_values([1, 5, 6], {a: 1, b: 2, c: 3, d: 4}) == {a: 1}
10297 template <typename MapType, typename ValueContainer>
10298 MapType map_keep_values(const ValueContainer& values, const MapType& map)
10299 {
10300     static_assert(std::is_same<
10301         typename ValueContainer::value_type,
10302         typename MapType::mapped_type>::value,
10303         "Value types do not match.");
10304     return map_keep_if_value(
10305         bind_2nd_of_2(is_elem_of<ValueContainer>, values), map);
10306 }
10307 
10308 // API search type: map_drop_values : ([value], Map key val) -> Map key val
10309 // fwd bind count: 1
10310 // Keeps only the pairs of the map not found in the value list.
10311 // Inverse of map_keep_values.
10312 // map_drop_values([2, 3], {a: 1, b: 2, c: 3, d: 4}) == {a: 1, d: 4}
10313 template <typename MapType, typename ValueContainer>
10314 MapType map_drop_values(const ValueContainer& values, const MapType& map)
10315 {
10316     static_assert(std::is_same<
10317         typename ValueContainer::value_type,
10318         typename MapType::mapped_type>::value,
10319         "Value types do not match.");
10320     return map_drop_if_value(
10321         bind_2nd_of_2(is_elem_of<ValueContainer>, values), map);
10322 }
10323 
10324 // API search type: map_pluck : (key, [Map key val]) -> [val]
10325 // fwd bind count: 1
10326 // Extracts values to a specific key from a list of maps.
10327 // map_pluck('a', [{a: 1, b: 2}, {a: 3}, {c: 4}]) == [Just 1, Just 3, Nothing]
10328 template <typename MapContainer,
10329     typename ContainerOut =
10330         std::vector<maybe<typename MapContainer::value_type::mapped_type>>,
10331     typename MapType = typename MapContainer::value_type,
10332     typename Key = typename MapType::key_type,
10333     typename Val = typename MapType::mapped_type>
10334 ContainerOut map_pluck(const Key& key, const MapContainer& maps)
10335 {
10336     return transform_convert<ContainerOut>(
10337         bind_2nd_of_2(get_from_map<MapType>, key), maps);
10338 }
10339 
10340 // API search type: choose : ([(a, b)], a) -> Maybe b
10341 // fwd bind count: 1
10342 // Selects a value assigned to a key iff the key exists exactly once.
10343 // choose([(1,a), (2,b)], 2) == Just b;
10344 // choose([(1,a), (1,b)], 2) == Nothing;
10345 // choose([(1,a), (2,b)], 3) == Nothing;
10346 template<typename Key, typename Val>
choose(const std::vector<std::pair<Key,Val>> & pairs,const Key & x)10347 maybe<Val> choose(const std::vector<std::pair<Key, Val>>& pairs, const Key& x)
10348 {
10349     if (count(x, transform(fst<Key, Val>, pairs)) != 1)
10350         return {};
10351     return get_from_map(pairs_to_map<std::unordered_map<Key, Val>>(pairs), x);
10352 }
10353 
10354 // API search type: choose_by : ([((a -> Bool), b)], a) -> Maybe b
10355 // fwd bind count: 2
10356 // Iff exactly one predicate is fulfilled
10357 // the value assigned to this predicate is selected.
10358 // choose_by([(is_even,a), (is_bigger_than_3,b)], 2) == Just a;
10359 // choose_by([(is_even,a), (is_bigger_than_3,b)], 5) == Just b;
10360 // choose_by([(is_even,a), (is_bigger_than_3,b)], 1) == Nothing;
10361 // choose_by([(is_even,a), (is_bigger_than_3,b)], 4) == Nothing;
10362 template<typename Key, typename Val>
choose_by(const std::vector<std::pair<std::function<bool (const Key &)>,Val>> & pairs,const Key & x)10363 maybe<Val> choose_by(
10364     const std::vector<std::pair<std::function<bool(const Key&)>, Val>>& pairs,
10365     const Key& x)
10366 {
10367     maybe<Val> result;
10368     for (const auto& p : pairs)
10369     {
10370         if (internal::invoke(p.first, x))
10371         {
10372             if (is_just(result))
10373             {
10374                 return nothing<Val>();
10375             }
10376             result = p.second;
10377         }
10378     }
10379     return result;
10380 }
10381 
10382 // API search type: choose_lazy : ([(a, (() -> b))], a) -> Maybe b
10383 // fwd bind count: 1
10384 // Evaluates a lazy value assigned to a key iff the key exists exactly once.
10385 // choose_lazy([(1,a), (2,b)], 2) == Just b();
10386 // choose_lazy([(1,a), (1,b)], 2) == Nothing;
10387 // choose_lazy([(1,a), (2,b)], 3) == Nothing;
10388 template <typename Key, typename ValStub>
choose_lazy(const std::vector<std::pair<Key,ValStub>> & pairs,const Key & x)10389 auto choose_lazy(const std::vector<std::pair<Key, ValStub>>& pairs,
10390                  const Key& x)
10391 {
10392     using Ret = maybe<std::decay_t<internal::invoke_result_t<ValStub>>>;
10393     const auto res = choose(pairs, x);
10394     if (res.is_nothing())
10395         return Ret{};
10396     else
10397         return Ret{res.unsafe_get_just()()};
10398 }
10399 
10400 // API search type: choose_by_lazy : ([((a -> Bool), (() -> b))], a) -> Maybe b
10401 // fwd bind count: 2
10402 // Iff exactly one predicate is fulfilled
10403 // the lazy value assigned to this predicate is evaluated.
10404 // choose_by_lazy([(is_even,a), (is_bigger_than_3,b)], 2) == Just a();
10405 // choose_by_lazy([(is_even,a), (is_bigger_than_3,b)], 5) == Just b();
10406 // choose_by_lazy([(is_even,a), (is_bigger_than_3,b)], 1) == Nothing;
10407 // choose_by_lazy([(is_even,a), (is_bigger_than_3,b)], 4) == Nothing;
10408 template <typename Key, typename ValStub>
choose_by_lazy(const std::vector<std::pair<std::function<bool (const Key &)>,ValStub>> & pairs,const Key & x)10409 auto choose_by_lazy(
10410     const std::vector<std::pair<std::function<bool(const Key&)>, ValStub>>& pairs,
10411     const Key& x)
10412 {
10413     using Ret = maybe<std::decay_t<internal::invoke_result_t<ValStub>>>;
10414 
10415     const auto res = choose_by(pairs, x);
10416     if (res.is_nothing())
10417         return Ret{};
10418     else
10419         return Ret{res.unsafe_get_just()()};
10420 }
10421 
10422 // API search type: choose_def : (b, [(a, b)], a) -> b
10423 // fwd bind count: 1
10424 // Selects a value assigned to a key iff the key exists exactly once,
10425 // otherwise returns the given default value.
10426 // choose_def(c, [(1,a), (2,b)], 2) == b;
10427 // choose_def(c, [(1,a), (1,b)], 2) == c;
10428 // choose_def(c, [(1,a), (2,b)], 3) == c;
10429 template<typename Key, typename Val>
choose_def(const Val & def,const std::vector<std::pair<Key,Val>> & pairs,const Key & x)10430 Val choose_def(const Val& def,
10431     const std::vector<std::pair<Key, Val>>& pairs, const Key& x)
10432 {
10433     if (count(x, transform(fst<Key, Val>, pairs)) != 1)
10434         return def;
10435     return get_from_map_with_def(
10436         pairs_to_map<std::unordered_map<Key, Val>>(pairs), def, x);
10437 }
10438 
10439 // API search type: choose_by_def : (b, [((a -> Bool), b)], a) -> b
10440 // fwd bind count: 2
10441 // Iff exactly one predicate is fulfilled
10442 // the value assigned to this predicate is selected.
10443 // Otherwise the given default value is returned.
10444 // choose_by_def(c, [(is_even,a), (is_bigger_than_3,b)], 2) == Just a;
10445 // choose_by_def(c, [(is_even,a), (is_bigger_than_3,b)], 5) == Just b;
10446 // choose_by_def(c, [(is_even,a), (is_bigger_than_3,b)], 1) == c;
10447 // choose_by_def(c, [(is_even,a), (is_bigger_than_3,b)], 4) == c;
10448 template<typename Key, typename Val>
choose_by_def(const Val & def,const std::vector<std::pair<std::function<bool (const Key &)>,Val>> & pairs,const Key & x)10449 Val choose_by_def(const Val& def,
10450     const std::vector<std::pair<std::function<bool(const Key&)>, Val>>& pairs,
10451     const Key& x)
10452 {
10453     return just_with_default(def, choose_by(pairs, x));
10454 }
10455 
10456 // API search type: choose_def_lazy : ((() -> b), [(a, (() -> b))], a) -> b
10457 // fwd bind count: 1
10458 // Evaluates a lazy value assigned to a key iff the key exists exactly once,
10459 // otherwise evaluates the given default lazy value.
10460 // choose_def_lazy(c, [(1,a), (2,b)], 2) == b();
10461 // choose_def_lazy(c, [(1,a), (1,b)], 2) == c();
10462 // choose_def_lazy(c, [(1,a), (2,b)], 3) == c();
10463 template <typename Key, typename ValStub>
choose_def_lazy(const ValStub & def,const std::vector<std::pair<Key,ValStub>> & pairs,const Key & x)10464 auto choose_def_lazy(const ValStub& def,
10465                      const std::vector<std::pair<Key, ValStub>>& pairs,
10466                      const Key& x)
10467 {
10468     return choose_def(def, pairs, x)();
10469 }
10470 
10471 // API search type: choose_by_def_lazy : ((() -> b), [((a -> Bool), (() -> b))], a) -> b
10472 // fwd bind count: 2
10473 // Iff exactly one predicate is fulfilled
10474 // the value assigned to this predicate is evaluated.
10475 // Otherwise the given default value is evaluated and returned.
10476 // choose_by_def_lazy(c, [(is_even,a), (is_bigger_than_3,b)], 2) == Just a();
10477 // choose_by_def_lazy(c, [(is_even,a), (is_bigger_than_3,b)], 5) == Just b();
10478 // choose_by_def_lazy(c, [(is_even,a), (is_bigger_than_3,b)], 1) == c();
10479 // choose_by_def_lazy(c, [(is_even,a), (is_bigger_than_3,b)], 4) == c();
10480 template <typename Key, typename ValStub>
choose_by_def_lazy(const ValStub & def,const std::vector<std::pair<std::function<bool (const Key &)>,ValStub>> & pairs,const Key & x)10481 auto choose_by_def_lazy(
10482     const ValStub& def,
10483     const std::vector<std::pair<std::function<bool(const Key&)>, ValStub>>& pairs,
10484     const Key& x)
10485 {
10486     return choose_by_def(def, pairs, x)();
10487 }
10488 
10489 } // namespace fplus
10490 
10491 //
10492 // optimize.hpp
10493 //
10494 
10495 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
10496 // https://github.com/Dobiasd/FunctionalPlus
10497 // Distributed under the Boost Software License, Version 1.0.
10498 // (See accompanying file LICENSE_1_0.txt or copy at
10499 //  http://www.boost.org/LICENSE_1_0.txt)
10500 
10501 
10502 
10503 //
10504 // transform.hpp
10505 //
10506 
10507 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
10508 // https://github.com/Dobiasd/FunctionalPlus
10509 // Distributed under the Boost Software License, Version 1.0.
10510 // (See accompanying file LICENSE_1_0.txt or copy at
10511 //  http://www.boost.org/LICENSE_1_0.txt)
10512 
10513 
10514 
10515 //
10516 // split.hpp
10517 //
10518 
10519 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
10520 // https://github.com/Dobiasd/FunctionalPlus
10521 // Distributed under the Boost Software License, Version 1.0.
10522 // (See accompanying file LICENSE_1_0.txt or copy at
10523 //  http://www.boost.org/LICENSE_1_0.txt)
10524 
10525 
10526 
10527 
10528 //
10529 // internal/split.hpp
10530 //
10531 
10532 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
10533 // https://github.com/Dobiasd/FunctionalPlus
10534 // Distributed under the Boost Software License, Version 1.0.
10535 // (See accompanying file LICENSE_1_0.txt or copy at
10536 //  http://www.boost.org/LICENSE_1_0.txt)
10537 
10538 
10539 #include <iterator>
10540 #include <utility>
10541 
10542 
10543 
10544 namespace fplus
10545 {
10546 namespace internal
10547 {
10548 template <typename GroupByCallable, typename F, typename ContainerIn>
group_on_labeled_impl(GroupByCallable group,F f,const ContainerIn & xs)10549 auto group_on_labeled_impl(GroupByCallable group, F f, const ContainerIn& xs)
10550 {
10551     const auto grouped = group(is_equal_by(f), xs);
10552     const auto attach_label = [f](const auto& g)
10553     {
10554         using std::begin;
10555         return std::make_pair(internal::invoke(f, *begin(g)), g);
10556     };
10557     return fplus::transform(attach_label, grouped);
10558 }
10559 }
10560 }
10561 
10562 namespace fplus
10563 {
10564 
10565 // API search type: group_by : (((a, a) -> Bool), [a]) -> [[a]]
10566 // fwd bind count: 1
10567 // Arrange the elements into groups using a given predicate.
10568 // Only groups of consecutive elements are formed.
10569 // For a version scanning the whole container see group_globally_by.
10570 // group_by((==), [1,2,2,2,3,2,2,4,5,5]) == [[1],[2,2,2],[3],[2,2],[4],[5,5]]
10571 // BinaryPredicate p is a (not neccessarily transitive) connectivity check.
10572 // O(n)
10573 template <typename BinaryPredicate, typename ContainerIn,
10574         typename ContainerOut = typename std::vector<ContainerIn>>
group_by(BinaryPredicate p,const ContainerIn & xs)10575 ContainerOut group_by(BinaryPredicate p, const ContainerIn& xs)
10576 {
10577     // ContainerOut is not deduced to
10578     // SameContNewType(ContainerIn, ContainerIn)
10579     // here, since ContainerIn could be a std::string.
10580     internal::check_binary_predicate_for_container<BinaryPredicate, ContainerIn>();
10581     static_assert(std::is_same<ContainerIn,
10582         typename ContainerOut::value_type>::value,
10583         "Containers do not match.");
10584     ContainerOut result;
10585     if (is_empty(xs))
10586         return result;
10587     typedef typename ContainerOut::value_type InnerContainerOut;
10588     *internal::get_back_inserter(result) = InnerContainerOut(1, xs.front());
10589     for (auto it = ++std::begin(xs); it != std::end(xs); ++it)
10590     {
10591         if (internal::invoke(p, result.back().back(), *it))
10592             *internal::get_back_inserter(result.back()) = *it;
10593         else
10594             *internal::get_back_inserter(result) = InnerContainerOut(1, *it);
10595     }
10596     return result;
10597 }
10598 
10599 // API search type: group_on : ((a -> b), [a]) -> [[a]]
10600 // fwd bind count: 1
10601 // Arrange elements equal after applying a transformer into groups.
10602 // Only groups of consecutive elements are formed.
10603 // For a version scanning the whole container see group_globally_on.
10604 // group_on((mod 10), [12,22,34]) == [[12,22],[34]]
10605 // O(n)
10606 template <typename F, typename ContainerIn>
group_on(F f,const ContainerIn & xs)10607 auto group_on(F f, const ContainerIn& xs)
10608 {
10609     return group_by(is_equal_by(f), xs);
10610 }
10611 
10612 // API search type: group_on_labeled : ((a -> b), [a]) -> [(b, [a])]
10613 // fwd bind count: 1
10614 // Arrange elements equal after applying a transformer into groups,
10615 // adding the transformation result as a label to the group.
10616 // Only groups of consecutive elements are formed.
10617 // For a version scanning the whole container see group_globally_on_labeled.
10618 // group_on_labeled((mod 10), [12,22,34]) == [(2,[12,22]), (4,[34])]
10619 // O(n)
10620 template <typename F, typename ContainerIn>
group_on_labeled(F f,const ContainerIn & xs)10621 auto group_on_labeled(F f, const ContainerIn& xs)
10622 {
10623     const auto group = [](auto f1, const auto& xs1)
10624     {
10625         return group_by(f1, xs1);
10626     };
10627 
10628     return internal::group_on_labeled_impl(group, f, xs);
10629 }
10630 
10631 // API search type: group : [a] -> [[a]]
10632 // fwd bind count: 0
10633 // Arrange equal elements into groups.
10634 // Only groups of consecutive elements are formed.
10635 // For a version scanning the whole container see group_globally.
10636 // group([1,2,2,2,3,2,2,4,5,5]) == [[1],[2,2,2],[3],[2,2],[4],[5,5]]
10637 // O(n)
10638 template <typename ContainerIn,
10639         typename ContainerOut = typename std::vector<ContainerIn>>
group(const ContainerIn & xs)10640 ContainerOut group(const ContainerIn& xs)
10641 {
10642     static_assert(std::is_same<ContainerIn,
10643         typename ContainerOut::value_type>::value,
10644         "Containers do not match.");
10645     typedef typename ContainerIn::value_type T;
10646     auto pred = [](const T& x, const T& y) { return x == y; };
10647     return group_by<decltype(pred), ContainerIn, ContainerOut>(pred, xs);
10648 }
10649 
10650 // API search type: group_globally_by : (((a, a) -> Bool), [a]) -> [[a]]
10651 // fwd bind count: 1
10652 // Arrange equal elements into groups.
10653 // group_globally_by((==), [1,2,2,2,3,2,2,4,5,5])
10654 // == [[1],[2,2,2,2,2],[3],[4],[5,5]]
10655 // BinaryPredicate p is a
10656 // transitive (whenever p(x,y) and p(y,z), then also p(x,z)) equality check.
10657 // O(n^2)
10658 // If you need O(n*log(n)), sort and then use group_by
10659 template <typename BinaryPredicate, typename ContainerIn,
10660         typename ContainerOut = typename std::vector<ContainerIn>>
group_globally_by(BinaryPredicate p,const ContainerIn & xs)10661 ContainerOut group_globally_by(BinaryPredicate p, const ContainerIn& xs)
10662 {
10663     internal::check_binary_predicate_for_container<BinaryPredicate, ContainerIn>();
10664     static_assert(std::is_same<ContainerIn,
10665         typename ContainerOut::value_type>::value,
10666         "Containers do not match.");
10667     typedef typename ContainerOut::value_type InnerContainerOut;
10668     ContainerOut result;
10669     for (const auto& x : xs)
10670     {
10671         bool found = false;
10672         for (auto& ys : result)
10673         {
10674             if (internal::invoke(p, x, ys.back()))
10675             {
10676                 *internal::get_back_inserter(ys) = x;
10677                 found = true;
10678                 break;
10679             }
10680         }
10681         if (!found)
10682         {
10683             *internal::get_back_inserter(result) = InnerContainerOut(1, x);
10684         }
10685     }
10686     return result;
10687 }
10688 
10689 // API search type: group_globally_on : ((a -> b), [a]) -> [[a]]
10690 // fwd bind count: 1
10691 // Arrange elements equal after applying a transformer into groups.
10692 // group_globally_on((mod 10), [12,34,22]) == [[12,22],[34]]
10693 // O(n^2)
10694 // If you need O(n*log(n)), sort and then use group_on
10695 template <typename F, typename ContainerIn>
group_globally_on(F f,const ContainerIn & xs)10696 auto group_globally_on(F f, const ContainerIn& xs)
10697 {
10698     return group_globally_by(is_equal_by(f), xs);
10699 }
10700 
10701 // API search type: group_globally_on_labeled : ((a -> b), [a]) -> [(b, [a])]
10702 // fwd bind count: 1
10703 // Arrange elements equal after applying a transformer into groups,
10704 // adding the transformation result as a label to the group.
10705 // group_globally_on_labeled((mod 10), [12,34,22]) == [(2,[12,22]),(4, [34])]
10706 // O(n^2)
10707 // If you need O(n*log(n)), sort and then use group_on_labeled
10708 template <typename F, typename ContainerIn>
group_globally_on_labeled(F f,const ContainerIn & xs)10709 auto group_globally_on_labeled(F f, const ContainerIn& xs)
10710 {
10711     const auto group = [](auto f1, const auto& xs1)
10712     {
10713         return group_globally_by(f1, xs1);
10714     };
10715 
10716     return internal::group_on_labeled_impl(group, f, xs);
10717 }
10718 
10719 // API search type: group_globally : [a] -> [[a]]
10720 // fwd bind count: 0
10721 // Arrange equal elements into groups.
10722 // group_globally([1,2,2,2,3,2,2,4,5,5]) == [[1],[2,2,2,2,2],[3],[4],[5,5]]
10723 // O(n^2)
10724 // If you need O(n*log(n)), sort and then use group
10725 template <typename ContainerIn,
10726         typename ContainerOut = typename std::vector<ContainerIn>>
group_globally(const ContainerIn & xs)10727 ContainerOut group_globally(const ContainerIn& xs)
10728 {
10729     static_assert(std::is_same<ContainerIn,
10730         typename ContainerOut::value_type>::value,
10731         "Containers do not match.");
10732     typedef typename ContainerIn::value_type T;
10733     auto pred = [](const T& x, const T& y) { return x == y; };
10734     return group_globally_by(pred, xs);
10735 }
10736 
10737 // API search type: cluster_by : (((a, a) -> Bool), [a]) -> [[a]]
10738 // fwd bind count: 1
10739 // Groups connected components, stable regarding initial order.
10740 // cluster_by(\x y -> abs (y - x) <= 3), [2,3,6,4,12,11,20,23,8,4])
10741 // == [[2,3,6,4,12,11,8,4],[20,23]]
10742 // BinaryPredicate p is a connectivity check, being
10743 //  a) commutative (p(x,y) = p(y,x))
10744 //  b) reflexive (p(x,x) = true)
10745 //  c) not neccessarily transitive, but can be
10746 // O(n^2), memory complexity also O(n^2)
10747 template <typename BinaryPredicate, typename ContainerIn,
10748         typename ContainerOut = typename std::vector<ContainerIn>>
cluster_by(BinaryPredicate p,const ContainerIn & xs)10749 ContainerOut cluster_by(BinaryPredicate p, const ContainerIn& xs)
10750 {
10751     internal::check_binary_predicate_for_container<BinaryPredicate, ContainerIn>();
10752     static_assert(std::is_same<ContainerIn,
10753         typename ContainerOut::value_type>::value,
10754         "Containers do not match.");
10755 
10756     typedef std::vector<unsigned char> bools;
10757     bools zero_filled_row(size_of_cont(xs), 0);
10758 
10759     // adjecency matrix
10760     typedef std::vector<bools> boolss;
10761     boolss adj_mat(size_of_cont(xs), zero_filled_row);
10762 
10763     for (const auto& idx_and_val_y : enumerate(xs))
10764     {
10765         auto idx_y = idx_and_val_y.first;
10766         auto val_y = idx_and_val_y.second;
10767         for (const auto& idx_and_val_x : enumerate(xs))
10768         {
10769             auto idx_x = idx_and_val_x.first;
10770             auto val_x = idx_and_val_x.second;
10771             if (internal::invoke(p, val_y, val_x))
10772             {
10773                 adj_mat[idx_y][idx_x] = 1;
10774             }
10775         }
10776     }
10777 
10778     bools already_used = zero_filled_row;
10779     auto is_already_used = [&](std::size_t i) -> bool
10780     {
10781         return already_used[i] != 0;
10782     };
10783 
10784     typedef std::vector<std::size_t> idxs;
10785     typedef std::vector<idxs> idxss;
10786 
10787     auto bools_to_idxs = [](const bools& activations) -> idxs
10788     {
10789         auto unsigned_char_to_bool = [](unsigned char x)
10790         {
10791             return x != 0;
10792         };
10793         return find_all_idxs_by(unsigned_char_to_bool, activations);
10794     };
10795 
10796     idxss idx_clusters;
10797     std::function<void(std::size_t)> process_idx = [&](std::size_t idx) -> void
10798     {
10799         auto connected_idxs = bools_to_idxs(adj_mat[idx]);
10800         auto new_connected_idxs = drop_if(is_already_used, connected_idxs);
10801         if (is_empty(new_connected_idxs))
10802         {
10803             return;
10804         }
10805         idx_clusters.back() = append(idx_clusters.back(), new_connected_idxs);
10806         for (const auto& new_idx : new_connected_idxs)
10807         {
10808             already_used[new_idx] = 1;
10809         }
10810         for (const auto& new_idx : new_connected_idxs)
10811         {
10812             process_idx(new_idx);
10813         }
10814     };
10815 
10816     typedef typename ContainerOut::value_type InnerContainerOut;
10817 
10818     for (const auto& idx : all_idxs(xs))
10819     {
10820         if (is_already_used(idx))
10821         {
10822             continue;
10823         }
10824         *internal::get_back_inserter(idx_clusters) = idxs();
10825         *internal::get_back_inserter(idx_clusters.back()) = idx;
10826         already_used[idx] = 1;
10827         process_idx(idx);
10828     }
10829 
10830     typedef typename ContainerIn::value_type T;
10831 
10832     auto idx_to_val = [&](std::size_t idx) -> T
10833     {
10834         return elem_at_idx(idx, xs);
10835     };
10836 
10837     auto idxs_to_vals = [&](const idxs& val_idxs) -> InnerContainerOut
10838     {
10839         return transform_convert<InnerContainerOut>(idx_to_val, sort(val_idxs));
10840     };
10841 
10842     return transform_convert<ContainerOut>(idxs_to_vals, idx_clusters);
10843 }
10844 
10845 // API search type: split_by : ((a -> Bool), Bool, [a]) -> [[a]]
10846 // fwd bind count: 2
10847 // Split a sequence at every element fulfilling a predicate.
10848 // The splitting elements are discarded.
10849 // split_by(is_even, true, [1,3,2,2,5,5,3,6,7,9]) == [[1,3],[],[5,5,3],[7,9]]
10850 // also known as split_when
10851 // O(n)
10852 template <typename UnaryPredicate, typename ContainerIn,
10853         typename ContainerOut = typename std::vector<ContainerIn>>
split_by(UnaryPredicate pred,bool allow_empty,const ContainerIn & xs)10854 ContainerOut split_by
10855         (UnaryPredicate pred, bool allow_empty, const ContainerIn& xs)
10856 {
10857     internal::check_unary_predicate_for_container<UnaryPredicate, ContainerIn>();
10858     static_assert(std::is_same<ContainerIn,
10859         typename ContainerOut::value_type>::value,
10860         "Containers do not match.");
10861 
10862     if (allow_empty && is_empty(xs))
10863     {
10864         return {{}};
10865     }
10866 
10867     ContainerOut result;
10868     auto itOut = internal::get_back_inserter(result);
10869     auto start = std::begin(xs);
10870 
10871     while (start != std::end(xs))
10872     {
10873         const auto stop = std::find_if(start, std::end(xs), pred);
10874         if (start != stop || allow_empty)
10875         {
10876             *itOut = { start, stop };
10877         }
10878         if (stop == std::end(xs))
10879         {
10880             break;
10881         }
10882         start = internal::add_to_iterator(stop);
10883         if (allow_empty && start == std::end(xs))
10884         {
10885             *itOut = typename ContainerOut::value_type();
10886         }
10887     }
10888     return result;
10889 }
10890 
10891 // API search type: split_by_keep_separators : ((a -> Bool), [a]) -> [[a]]
10892 // fwd bind count: 1
10893 // Split a sequence at every element fulfilling a predicate.
10894 // The splitting elements are kept.
10895 // split_by_keep_separators(is_even, true, [1,3,2,2,5,5,3,6,7,9])
10896 // == [[1,3],[2],[2,5,5,3],[6,7,9]]
10897 // O(n)
10898 template <typename UnaryPredicate, typename ContainerIn,
10899         typename ContainerOut = typename std::vector<ContainerIn>>
split_by_keep_separators(UnaryPredicate pred,const ContainerIn & xs)10900 ContainerOut split_by_keep_separators
10901         (UnaryPredicate pred, const ContainerIn& xs)
10902 {
10903     internal::check_unary_predicate_for_container<UnaryPredicate, ContainerIn>();
10904     static_assert(std::is_same<ContainerIn,
10905         typename ContainerOut::value_type>::value,
10906         "Containers do not match.");
10907     ContainerOut result;
10908     if (is_empty(xs))
10909         return result;
10910     auto itOut = internal::get_back_inserter(result);
10911     auto start = std::begin(xs);
10912     while (start != std::end(xs))
10913     {
10914         const auto stop = std::find_if(
10915             internal::add_to_iterator(start), std::end(xs), pred);
10916         *itOut = { start, stop };
10917         if (stop == std::end(xs))
10918         {
10919             break;
10920         }
10921         start = stop;
10922     }
10923     return result;
10924 }
10925 
10926 // API search type: split : (a, Bool, [a]) -> [[a]]
10927 // fwd bind count: 2
10928 // Split a sequence at every element equal to x.
10929 // The splitting elements are discarded.
10930 // split(0, true, [1,3,2,0,0,6,0,7,5]) == [[1,3,2],[],[6],[7,5]]
10931 // O(n)
10932 template <typename ContainerIn,
10933         typename T = typename ContainerIn::value_type>
split(const T & x,bool allow_empty,const ContainerIn & xs)10934 auto split(const T& x, bool allow_empty, const ContainerIn& xs)
10935 {
10936     return split_by(is_equal_to(x), allow_empty, xs);
10937 }
10938 
10939 // API search type: split_one_of : ([a], Bool, [a]) -> [[a]]
10940 // fwd bind count: 2
10941 // Split a sequence at every element present in delimiters.
10942 // The splitting elements are discarded.
10943 // Also known as split_words_by_many.
10944 // split_one_of([0,3], true [1,3,2,0,0,6,0,7,5]) == [[1],[2],[],[6],[7,5]]
10945 // split_one_of(" o", false, "How are u?") == ["H","w","are","u?"]
10946 // O(n)
10947 template <typename ContainerIn,
10948         typename ContainerDelims>
split_one_of(const ContainerDelims delimiters,bool allow_empty,const ContainerIn & xs)10949 auto split_one_of(
10950     const ContainerDelims delimiters, bool allow_empty, const ContainerIn& xs)
10951 {
10952     const auto pred = [&](const typename ContainerIn::value_type& x) -> bool
10953     {
10954         return is_elem_of(x, delimiters);
10955     };
10956     return split_by(pred, allow_empty, xs);
10957 }
10958 
10959 // API search type: split_keep_separators : ((a -> Bool), [a]) -> [[a]]
10960 // fwd bind count: 1
10961 // Split a sequence at every element equal to x.
10962 // The splitting elements are kept.
10963 // split_keep_separators(2, true, [1,3,2,2,5,5,3,2,7,9])
10964 // == [[1,3],[2],[2,5,5,3],[6,7,9]]
10965 // O(n)
10966 template <typename ContainerIn,
10967         typename T = typename ContainerIn::value_type>
split_keep_separators(const T & x,const ContainerIn & xs)10968 auto split_keep_separators(const T& x, const ContainerIn& xs)
10969 {
10970     return split_by_keep_separators(is_equal_to(x), xs);
10971 }
10972 
10973 // API search type: split_at_idx : (Int, [a]) -> ([a], [a])
10974 // fwd bind count: 1
10975 // Split a sequence at a specific position.
10976 // split_at_idx(2, [0,1,2,3,4]) == ([0,1],[2,3,4])
10977 template <typename Container>
split_at_idx(std::size_t idx,const Container & xs)10978 std::pair<Container, Container> split_at_idx
10979         (std::size_t idx, const Container& xs)
10980 {
10981     assert(idx <= size_of_cont(xs));
10982     return make_pair(get_segment(0, idx, xs),
10983         get_segment(idx, size_of_cont(xs), xs));
10984 }
10985 
10986 // API search type: insert_at_idx : (Int, a, [a]) -> [a]
10987 // fwd bind count: 2
10988 // Insert an element into a sequence at a specific position.
10989 // insert_at_idx(2, 0, [1,2,3,4]) == [1,2,0,3,4].
10990 template <typename Container,
10991         typename T = typename Container::value_type>
10992 Container insert_at_idx(std::size_t idx, const T& x, const Container& xs)
10993 {
10994     const auto splitted = split_at_idx(idx, xs);
10995     return concat(std::vector<Container>(
10996         {
10997             splitted.first,
10998             singleton_seq<T, Container>(x),
10999             splitted.second
11000         }));
11001 }
11002 
11003 // API search type: partition : ((a -> Bool), [a]) -> ([a], [a])
11004 // fwd bind count: 1
11005 // Split a sequence into two groups.
11006 // The first group contains all elements fulfilling the predicate.
11007 // The second group contains the remaining elements.
11008 // partition(is_even, [0,1,1,3,7,2,3,4]) == ([0,2,4],[1,1,3,7,3])
11009 template <typename UnaryPredicate, typename Container>
partition(UnaryPredicate pred,const Container & xs)11010 std::pair<Container, Container> partition
11011         (UnaryPredicate pred, const Container& xs)
11012 {
11013     internal::check_unary_predicate_for_container<UnaryPredicate, Container>();
11014     Container matching;
11015     Container notMatching;
11016     auto itOutMatching = internal::get_back_inserter(matching);
11017     auto itOutNotMatching = internal::get_back_inserter(notMatching);
11018     for (const auto& x : xs)
11019     {
11020         if (internal::invoke(pred, x))
11021             *itOutMatching = x;
11022         else
11023             *itOutNotMatching = x;
11024     }
11025     return make_pair(matching, notMatching);
11026 }
11027 
11028 // API search type: split_at_idxs : ([Int], [a]) -> [[a]]
11029 // fwd bind count: 1
11030 // Split a sequence at specific indices.
11031 // split_at_idxs([2,5], [0,1,2,3,4,5,6,7]) == [[0,1],[2,3,4],[5,6,7]]
11032 // split_at_idxs([2,5,5], [0,1,2,3,4,5,6,7]) == [[0,1],[2,3,4],[],[5,6,7]]
11033 template <typename ContainerIdxs, typename ContainerIn,
11034         typename ContainerOut = std::vector<ContainerIn>>
split_at_idxs(const ContainerIdxs & idxsIn,const ContainerIn & xs)11035 ContainerOut split_at_idxs(const ContainerIdxs& idxsIn, const ContainerIn& xs)
11036 {
11037     static_assert(std::is_same<typename ContainerIdxs::value_type, std::size_t>::value,
11038         "Indices must be std::size_t");
11039     static_assert(std::is_same<ContainerIn,
11040         typename ContainerOut::value_type>::value,
11041         "Containers do not match.");
11042     ContainerIdxs idxStartC = {0};
11043     ContainerIdxs idxEndC = {size_of_cont(xs)};
11044     std::vector<ContainerIdxs> containerIdxss = {idxStartC, idxsIn, idxEndC};
11045     auto idxs = concat(containerIdxss);
11046     auto idxsClean = sort(idxs);
11047     ContainerOut result;
11048     internal::prepare_container(result, size_of_cont(idxsClean) - 1);
11049     auto itOut = internal::get_back_inserter(result);
11050     auto idxPairs = overlapping_pairs(idxsClean);
11051     for (const auto& idxPair : idxPairs)
11052     {
11053         *itOut = get_segment(idxPair.first, idxPair.second, xs);
11054     }
11055     return result;
11056 }
11057 
11058 // API search type: split_every : (Int, [a]) -> [[a]]
11059 // fwd bind count: 1
11060 // Split a sequence every n elements.
11061 // split_every(3, [0,1,2,3,4,5,6,7]) == [[0,1,2],[3,4,5],[6,7]]
11062 // Also known as chunk or chunks.
11063 template <typename ContainerIn,
11064         typename ContainerOut = std::vector<ContainerIn>>
split_every(std::size_t n,const ContainerIn & xs)11065 ContainerOut split_every(std::size_t n, const ContainerIn& xs)
11066 {
11067     return split_at_idxs<
11068         std::vector<std::size_t>,
11069         ContainerIn,
11070         ContainerOut>(
11071             numbers_step<std::size_t>(
11072                 n, size_of_cont(xs), n),
11073             xs);
11074 }
11075 
11076 // API search type: split_by_token : ([a], Bool, [a]) -> [[a]]
11077 // fwd bind count: 2
11078 // Split a sequence at every segment matching a token.
11079 // split_by_token(", ", true, "foo, bar, baz") == ["foo", "bar", "baz"]
11080 template <typename ContainerIn,
11081         typename ContainerOut = typename std::vector<ContainerIn>>
split_by_token(const ContainerIn & token,bool allow_empty,const ContainerIn & xs)11082 ContainerOut split_by_token(const ContainerIn& token,
11083         bool allow_empty, const ContainerIn& xs)
11084 {
11085     static_assert(std::is_same<ContainerIn,
11086         typename ContainerOut::value_type>::value,
11087         "Containers do not match.");
11088     const auto token_begins =
11089         find_all_instances_of_token_non_overlapping(token, xs);
11090     const auto token_ends =
11091         transform(add_to<std::size_t>(size_of_cont(token)), token_begins);
11092     assert(is_sorted(interweave(token_begins, token_ends)));
11093 
11094     typedef std::vector<std::size_t> idx_vec;
11095     const auto segments = zip(
11096         fplus::append(idx_vec(1, 0), token_ends),
11097         fplus::append(token_begins, idx_vec(1, size_of_cont(xs))));
11098 
11099     ContainerOut result;
11100     auto itOut = internal::get_back_inserter(result);
11101     for (const auto& segment : segments)
11102     {
11103         if (segment.first != segment.second || allow_empty)
11104         *itOut = get_segment(segment.first, segment.second, xs);
11105     }
11106     return result;
11107 }
11108 
11109 // API search type: run_length_encode_by : (((a, a) -> Bool), [a]) -> [(Int, a)]
11110 // fwd bind count: 1
11111 // RLE using a specific binary predicate as equality check.
11112 // run_length_encode_by((==),[1,2,2,2,2,3,3,2)) == [(1,1),(4,2),(2,3),(1,2)]
11113 template <typename BinaryPredicate,
11114         typename ContainerIn,
11115         typename T = typename ContainerIn::value_type,
11116         typename ContainerOut =
11117             typename std::vector<std::pair<std::size_t, T>>>
run_length_encode_by(BinaryPredicate pred,const ContainerIn & xs)11118 ContainerOut run_length_encode_by(BinaryPredicate pred, const ContainerIn& xs)
11119 {
11120     internal::check_binary_predicate_for_container<BinaryPredicate, ContainerIn>();
11121     ContainerOut result;
11122     auto groups = group_by(pred, xs);
11123     auto group_to_pair = [](const ContainerIn& group) -> std::pair<std::size_t, T>
11124     {
11125         return std::make_pair(size_of_cont(group), group.front());
11126     };
11127     return transform(group_to_pair, groups);
11128 }
11129 
11130 // API search type: run_length_encode : [a] -> [(Int, a)]
11131 // fwd bind count: 0
11132 // RLE.
11133 // run_length_encode([1,2,2,2,2,3,3,2)) == [(1,1),(4,2),(2,3),(1,2)]
11134 template <typename ContainerIn,
11135         typename T = typename ContainerIn::value_type>
run_length_encode(const ContainerIn & xs)11136 auto run_length_encode(const ContainerIn& xs)
11137 {
11138     return run_length_encode_by(is_equal<T>, xs);
11139 }
11140 
11141 // API search type: run_length_decode : [(Int, a)] -> [a]
11142 // fwd bind count: 0
11143 // Inverse operation to run_length_encode.
11144 // run_length_decode([(1,1),(4,2),(2,3),(1,2)]) == [1,2,2,2,2,3,3,2)
11145 template <typename ContainerIn,
11146         typename Pair = typename ContainerIn::value_type,
11147         typename Cnt = typename Pair::first_type>
run_length_decode(const ContainerIn & pairs)11148 auto run_length_decode(const ContainerIn& pairs)
11149 {
11150     static_assert(std::is_convertible<Cnt, std::size_t>::value,
11151         "Count type must be convertible to std::size_t.");
11152     const auto pair_to_vec =
11153         [](const Pair& p)
11154     {
11155         return replicate(p.first, p.second);
11156     };
11157     return concat(transform(pair_to_vec, pairs));
11158 }
11159 
11160 // API search type: span : ((a -> Bool), [a]) -> ([a], [a])
11161 // fwd bind count: 1
11162 // span, applied to a predicate p and a list xs,
11163 // returns a tuple where first element is longest prefix (possibly empty)
11164 // of xs of elements that satisfy p
11165 // and second element is the remainder of the list.
11166 // span(is_even, [0,2,4,5,6,7,8]) == ([0,2,4], [5,6,7,8])
11167 template <typename Container, typename UnaryPredicate>
span(UnaryPredicate pred,const Container & xs)11168 std::pair<Container, Container> span(UnaryPredicate pred, const Container& xs)
11169 {
11170     auto maybeIdx = find_first_idx_by(logical_not(pred), xs);
11171     return {
11172         take(just_with_default<std::size_t>(size_of_cont(xs), maybeIdx), xs),
11173         drop(just_with_default<std::size_t>(size_of_cont(xs), maybeIdx), xs)
11174     };
11175 }
11176 
11177 // API search type: divvy : (Int, Int, [a]) -> [[a]]
11178 // fwd bind count: 2
11179 // Generates subsequences overlapping with a specific step.
11180 // divvy(5, 2, [0,1,2,3,4,5,6,7,8,9]) == [[0,1,2,3,4],[2,3,4,5,6],[4,5,6,7,8]]
11181 // divvy(length, 1, xs) is also known as aperture
11182 // divvy(1, step, xs) is also known as stride
11183 //     (but withouts the nested lists in the result)
11184 template <typename ContainerIn,
11185         typename ContainerOut = std::vector<ContainerIn>>
divvy(std::size_t length,std::size_t step,const ContainerIn & xs)11186 ContainerOut divvy(std::size_t length, std::size_t step, const ContainerIn& xs)
11187 {
11188     assert(length > 0);
11189     assert(step > 0);
11190     const auto start_idxs =
11191         numbers_step<std::size_t>(
11192             0, size_of_cont(xs) - (length - 1), step);
11193 
11194     ContainerOut result;
11195     internal::prepare_container(result, size_of_cont(start_idxs));
11196     auto itOut = internal::get_back_inserter(result);
11197 
11198     for (const auto start_idx : start_idxs)
11199     {
11200         *itOut = get_segment(start_idx, start_idx + length, xs);
11201     }
11202     return result;
11203 }
11204 
11205 // API search type: aperture : (Int, [a]) -> [[a]]
11206 // fwd bind count: 1
11207 // Generates overlapping subsequences.
11208 // aperture(5, [0,1,2,3,4,5,6]) == [[0,1,2,3,4],[1,2,3,4,5],[2,3,4,5,6]]
11209 template <typename ContainerIn,
11210         typename ContainerOut = std::vector<ContainerIn>>
aperture(std::size_t length,const ContainerIn & xs)11211 ContainerOut aperture(std::size_t length, const ContainerIn& xs)
11212 {
11213     assert(length > 0);
11214     const auto start_idxs =
11215         numbers<std::size_t>(
11216             0, size_of_cont(xs) - (length - 1));
11217 
11218     ContainerOut result;
11219     internal::prepare_container(result, size_of_cont(start_idxs));
11220     auto itOut = internal::get_back_inserter(result);
11221 
11222     for (const auto start_idx : start_idxs)
11223     {
11224         *itOut = get_segment(start_idx, start_idx + length, xs);
11225     }
11226     return result;
11227 }
11228 
11229 // API search type: stride : (Int, [a]) -> [a]
11230 // fwd bind count: 1
11231 // Keeps every nth element.
11232 // stride(3, [0,1,2,3,4,5,6,7]) == [0,3,6]
11233 template <typename Container>
stride(std::size_t step,const Container & xs)11234 Container stride(std::size_t step, const Container& xs)
11235 {
11236     assert(step > 0);
11237     Container ys;
11238     auto it = internal::get_back_inserter<Container>(ys);
11239     auto it_in = std::begin(xs);
11240     std::size_t i = 0;
11241     const auto xs_size = size_of_cont(xs);
11242     while(it_in != std::end(xs))
11243     {
11244         *it = *it_in;
11245         std::size_t increment = std::min(step, xs_size - i);
11246         internal::advance_iterator(it_in, increment);
11247         i += increment;
11248     }
11249     return ys;
11250 }
11251 
11252 // API search type: winsorize : (Float, [Float]) -> [Float]
11253 // fwd bind count: 1
11254 // Winsorizing
11255 // winsorize(0.1, [1,3,4,4,4,4,4,4,6,8]) == [3,3,4,4,4,4,4,4,6,6]
11256 template <typename Container>
winsorize(double trim_ratio,const Container & xs)11257 Container winsorize(double trim_ratio, const Container& xs)
11258 {
11259     if (size_of_cont(xs) < 2)
11260     {
11261         return xs;
11262     }
11263     trim_ratio = std::max(trim_ratio, 0.0);
11264     const auto xs_sorted = sort(xs);
11265     std::size_t amount =
11266         floor<double, std::size_t>(
11267             trim_ratio * static_cast<double>(size_of_cont(xs_sorted)));
11268     amount = std::min(size_of_cont(xs_sorted) / 2, amount);
11269     const auto parts = split_at_idxs(
11270         std::vector<std::size_t>({amount, size_of_cont(xs_sorted) - amount}),
11271         xs_sorted);
11272     assert(size_of_cont(parts) == 3);
11273     typedef typename Container::value_type T;
11274     if (is_empty(parts[1]))
11275     {
11276         return Container(size_of_cont(xs_sorted), median(xs_sorted));
11277     }
11278     else
11279     {
11280         const T lower = parts[1].front();
11281         const T upper = parts[1].back();
11282         const auto result = concat(std::vector<Container>({
11283             Container(amount, lower),
11284             parts[1],
11285             Container(amount, upper)}));
11286         assert(size_of_cont(result) == size_of_cont(xs_sorted));
11287         return result;
11288     }
11289 }
11290 
11291 // API search type: separate_on : ((a -> b), [a]) -> [[a]]
11292 // fwd bind count: 1
11293 // Separate elements equal after applying a transformer into groups.
11294 // separate_on((mod 10), [12,22,34]) == [[12,34],[22]]
11295 template <typename F, typename ContainerIn,
11296         typename ContainerOut = typename std::vector<ContainerIn>>
separate_on(F f,const ContainerIn & xs)11297 ContainerOut separate_on(F f, const ContainerIn& xs)
11298 {
11299     static_assert(std::is_same<ContainerIn,
11300         typename ContainerOut::value_type>::value,
11301         "Containers do not match.");
11302 
11303     ContainerOut result;
11304     if (is_empty(xs)) {
11305         return result;
11306     }
11307 
11308     const auto groups = group_globally_on(f, xs);
11309     bool found = true;
11310     auto itOut = internal::get_back_inserter(result);
11311     std::size_t index = 0;
11312     while (found) {
11313         typename ContainerOut::value_type sub_result;
11314         found = false;
11315         auto itOutInner = internal::get_back_inserter(sub_result);
11316         for (auto& group: groups) {
11317             if (size_of_cont(group) > index)
11318             {
11319                 *itOutInner = group[index];
11320                 found = true;
11321             }
11322         }
11323         if (found) {
11324             *itOut = sub_result;
11325             ++index;
11326         }
11327     }
11328     return result;
11329 }
11330 
11331 // API search type: separate : [a] -> [[a]]
11332 // fwd bind count: 0
11333 // Separate equal elements into groups.
11334 // separate([1, 2, 2, 3, 3, 4, 4, 4]) == [[1, 2, 3, 4], [2, 3, 4], [4]]
11335 template <typename ContainerIn,
11336         typename ContainerOut = typename std::vector<ContainerIn>>
separate(const ContainerIn & xs)11337 ContainerOut separate(const ContainerIn& xs)
11338 {
11339     static_assert(std::is_same<ContainerIn,
11340         typename ContainerOut::value_type>::value,
11341         "Containers do not match.");
11342     typedef typename ContainerIn::value_type T;
11343     return separate_on(identity<T>, xs);
11344 }
11345 
11346 } // namespace fplus
11347 
11348 
11349 #include <algorithm>
11350 #include <future>
11351 #include <iterator>
11352 #include <mutex>
11353 #include <random>
11354 
11355 namespace fplus
11356 {
11357 
11358 // API search type: transform_with_idx : (((Int, a) -> b), [a]) -> [b]
11359 // fwd bind count: 1
11360 // Apply a function to every index and corresponding element of a sequence.
11361 // transform_with_idx(f, [6, 4, 7]) == [f(0, 6), f(1, 4), f(2, 7)]
11362 template <typename F, typename ContainerIn,
11363     typename ContainerOut = typename internal::same_cont_new_t_from_binary_f<
11364         ContainerIn, F, std::size_t, typename ContainerIn::value_type, 0>::type>
transform_with_idx(F f,const ContainerIn & xs)11365 ContainerOut transform_with_idx(F f, const ContainerIn& xs)
11366 {
11367     internal::trigger_static_asserts<internal::binary_function_tag, F>();
11368     ContainerOut ys;
11369     internal::prepare_container(ys, size_of_cont(xs));
11370     auto it = internal::get_back_inserter<ContainerOut>(ys);
11371     std::size_t idx = 0;
11372     for (const auto& x : xs)
11373     {
11374         *it = internal::invoke(f, idx++, x);
11375     }
11376     return ys;
11377 }
11378 
11379 // API search type: transform_and_keep_justs : ((a -> Maybe b), [a]) -> [b]
11380 // fwd bind count: 1
11381 // Map function over values and drop resulting nothings.
11382 // Also known as filter_map.
11383 template <typename F, typename ContainerIn>
transform_and_keep_justs(F f,const ContainerIn & xs)11384 auto transform_and_keep_justs(F f, const ContainerIn& xs)
11385 {
11386     using X = typename ContainerIn::value_type;
11387     internal::
11388         trigger_static_asserts<internal::unary_function_tag, F, X>();
11389 
11390     using ContainerOut = typename internal::same_cont_new_t<
11391         ContainerIn,
11392         typename std::decay_t<internal::invoke_result_t<F, X>>::type>::type;
11393 
11394     auto transformed = transform(f, xs);
11395     return justs<decltype(transformed), ContainerOut>(transformed);
11396 }
11397 
11398 // API search type: transform_and_keep_oks : ((a -> Result b), [a]) -> [b]
11399 // fwd bind count: 1
11400 // Map function over values and drop resulting errors.
11401 template <typename F, typename ContainerIn>
transform_and_keep_oks(F f,const ContainerIn & xs)11402 auto transform_and_keep_oks(F f, const ContainerIn& xs)
11403 {
11404     using X = typename ContainerIn::value_type;
11405     internal::
11406         trigger_static_asserts<internal::unary_function_tag, F, X>();
11407 
11408     using ContainerOut = typename internal::same_cont_new_t<
11409         ContainerIn,
11410         typename std::decay_t<internal::invoke_result_t<F, X>>::ok_t>::type;
11411     auto transformed = transform(f, xs);
11412     return oks<decltype(transformed), ContainerOut>(transformed);
11413 }
11414 
11415 // API search type: transform_and_concat : ((a -> [b]), [a]) -> [b]
11416 // fwd bind count: 1
11417 // Map function over values and concat results.
11418 // Also known as flat_map or concat_map.
11419 template <typename F, typename ContainerIn>
transform_and_concat(F f,const ContainerIn & xs)11420 auto transform_and_concat(F f, const ContainerIn& xs)
11421 {
11422     internal::trigger_static_asserts<internal::unary_function_tag, F, typename ContainerIn::value_type>();
11423     return concat(transform(f, xs));
11424 }
11425 
11426 // API search type: replicate_elems : (Int, [a]) -> [a]
11427 // fwd bind count: 1
11428 // Replicate every element n times, concatenate the result.
11429 // replicate_elems(3, [1,2]) == [1, 1, 1, 2, 2, 2]
11430 template <typename Container>
replicate_elems(std::size_t n,const Container & xs)11431 Container replicate_elems(std::size_t n, const Container& xs)
11432 {
11433     typedef typename Container::value_type T;
11434     return transform_and_concat(bind_1st_of_2(replicate<T, Container>, n), xs);
11435 }
11436 
11437 // API search type: interleave : [[a]] -> [a]
11438 // fwd bind count: 0
11439 // Return a sequence that contains elements from the provided sequences
11440 // in alternating order. If one list runs out of items,
11441 // appends the items from the remaining list.
11442 // interleave([[1,2,3],[4,5],[6,7,8]]) == [1,4,6,2,5,7,3,8]
11443 template <typename ContainerIn,
11444     typename ContainerOut = typename ContainerIn::value_type>
interleave(const ContainerIn & xss)11445 ContainerOut interleave(const ContainerIn& xss)
11446 {
11447     typedef typename ContainerIn::value_type inner_t;
11448     typedef std::vector<typename inner_t::const_iterator> its_t;
11449     const auto inner_cbegin = [](const inner_t& xs) { return xs.cbegin(); };
11450     const auto inner_cend = [](const inner_t& xs) { return xs.cend(); };
11451     auto it_pairs = zip(
11452         transform_convert<its_t>(inner_cbegin, xss),
11453         transform_convert<its_t>(inner_cend, xss));
11454 
11455     ContainerOut result;
11456     const std::size_t length = sum(transform(size_of_cont<inner_t>, xss));
11457     internal::prepare_container(result, length);
11458     auto it_out = internal::get_back_inserter<ContainerOut>(result);
11459     bool still_appending = true;
11460     while (still_appending)
11461     {
11462         still_appending = false;
11463         for (auto& it_pair : it_pairs)
11464         {
11465             if (it_pair.first != it_pair.second)
11466             {
11467                 *it_out = *it_pair.first;
11468                 still_appending = true;
11469                 ++it_pair.first;
11470             }
11471         }
11472     }
11473     return result;
11474 }
11475 
11476 // API search type: transpose : [[a]] -> [[a]]
11477 // fwd bind count: 0
11478 // Transpose a nested sequence aka. table aka. two-dimensional matrix.
11479 // transpose([[1,2,3],[4,5,6],[7,8,9]]) == [[1,4,7],[2,5,8],[3,6,9]]
11480 // transpose([[1,2,3],[4,5],[7,8,9]]) == [[1,4,7],[2,5,8],[3,9]]
11481 template <typename Container>
transpose(const Container & rows)11482 Container transpose(const Container& rows)
11483 {
11484     if (is_empty(rows))
11485     {
11486         return {};
11487     }
11488     return split_every<typename Container::value_type, Container>(
11489         size_of_cont(rows), interleave(rows));
11490 }
11491 
11492 namespace internal
11493 {
11494 
11495 template <typename Container>
shuffle(internal::reuse_container_t,std::uint_fast32_t seed,Container && xs)11496 Container shuffle(internal::reuse_container_t,
11497     std::uint_fast32_t seed, Container&& xs)
11498 {
11499     std::mt19937 g(seed);
11500     std::shuffle(std::begin(xs), std::end(xs), g);
11501     return std::forward<Container>(xs);
11502 }
11503 
11504 template <typename Container>
shuffle(internal::create_new_container_t,std::uint_fast32_t seed,const Container & xs)11505 Container shuffle(internal::create_new_container_t,
11506     std::uint_fast32_t seed, const Container& xs)
11507 {
11508     Container ys = xs;
11509     return internal::shuffle(internal::reuse_container_t(), seed, std::move(ys));
11510 }
11511 
11512 } // namespace internal
11513 
11514 // API search type: shuffle : (Int, [a]) -> [a]
11515 // fwd bind count: 1
11516 // Returns a randomly shuffled version of xs.
11517 // Example call: shuffle(std::mt19937::default_seed, xs);
11518 // Example call: shuffle(std::random_device()(), xs);
11519 template <typename Container>
shuffle(std::uint_fast32_t seed,Container && xs)11520 auto shuffle(std::uint_fast32_t seed, Container&& xs)
11521 {
11522     return(internal::shuffle(internal::can_reuse_v<Container>{},
11523         seed, std::forward<Container>(xs)));
11524 }
11525 
11526 // API search type: sample : (Int, Int, [a]) -> [a]
11527 // fwd bind count: 2
11528 // Returns n random elements from xs without replacement.
11529 // n has to be smaller than or equal to the number of elements in xs.
11530 // Also known as rnd_select.
11531 // Example call: sample(std::mt19937::default_seed, 3, xs);
11532 // Example call: sample(std::random_device()(), 3, xs);
11533 template <typename Container>
sample(std::uint_fast32_t seed,std::size_t n,const Container & xs)11534 Container sample(std::uint_fast32_t seed, std::size_t n, const Container& xs)
11535 {
11536     assert(n <= size_of_cont(xs));
11537     return get_segment(0, n, shuffle(seed, xs));
11538 }
11539 
11540 // API search type: random_element : (Int, [a]) -> a
11541 // fwd bind count: 1
11542 // Returns one random element from xs.
11543 // xs must be non-empty.
11544 // Example call: random_element(std::mt19937::default_seed, xs)
11545 // Example call: random_element(std::random_device()(), xs)
11546 // Also known as choice.
11547 template <typename Container>
random_element(std::uint_fast32_t seed,const Container & xs)11548 typename Container::value_type random_element(
11549     std::uint_fast32_t seed, const Container& xs)
11550 {
11551     assert(is_not_empty(xs));
11552     std::mt19937 gen(seed);
11553     std::uniform_int_distribution<std::size_t> dis(0, size_of_cont(xs) - 1);
11554     return elem_at_idx(dis(gen), xs);
11555 }
11556 
11557 // API search type: random_elements : (Int, Int, [a]) -> a
11558 // fwd bind count: 2
11559 // Returns random elements from xs with replacement.
11560 // xs must be non-empty.
11561 // Example call: random_elements(std::mt19937::default_seed, 10, xs)
11562 // Example call: random_elements(std::random_device()(), 10, xs)
11563 template <typename Container>
random_elements(std::uint_fast32_t seed,std::size_t n,const Container & xs)11564 Container random_elements(
11565     std::uint_fast32_t seed, std::size_t n, const Container& xs)
11566 {
11567     assert(is_not_empty(xs));
11568     std::mt19937 gen(seed);
11569     std::uniform_int_distribution<std::size_t> dis(0, size_of_cont(xs) - 1);
11570     const auto draw = [&]() -> typename Container::value_type
11571     {
11572         return elem_at_idx(dis(gen), xs);
11573     };
11574     return generate<Container>(draw, n);
11575 }
11576 
11577 // API search type: apply_functions : ([(a -> b)], a) -> [b]
11578 // fwd bind count: 1
11579 // Applies a list of functions to a value.
11580 template <typename FunctionContainer,
11581           typename F = typename FunctionContainer::value_type,
11582           typename FIn>
apply_functions(const FunctionContainer & functions,const FIn & x)11583 auto apply_functions(const FunctionContainer& functions, const FIn& x)
11584 {
11585     internal::trigger_static_asserts<internal::unary_function_tag, F, FIn>();
11586 
11587     using FOut = std::decay_t<internal::invoke_result_t<F, FIn>>;
11588     using ContainerOut =
11589         typename internal::same_cont_new_t<FunctionContainer, FOut, 0>::type;
11590 
11591     ContainerOut ys;
11592     internal::prepare_container(ys, size_of_cont(functions));
11593     auto it = internal::get_back_inserter<ContainerOut>(ys);
11594     for (const auto& f : functions)
11595     {
11596         *it = internal::invoke(f, x);
11597     }
11598     return ys;
11599 }
11600 
11601 // API search type: apply_function_n_times : ((a -> a), Int, a) -> a
11602 // fwd bind count: 2
11603 // Applies a functional n times in a row.
11604 template <typename F, typename FIn>
apply_function_n_times(F f,std::size_t n,const FIn & x)11605 auto apply_function_n_times(F f, std::size_t n, const FIn& x)
11606 {
11607     internal::trigger_static_asserts<internal::unary_function_tag, F, FIn>();
11608     using FOut = std::decay_t<internal::invoke_result_t<F, FIn>>;
11609     static_assert(std::is_same<FOut, FIn>::value,
11610                   "Input and output of F must be the same type.");
11611     if (n == 0)
11612     {
11613         return x;
11614     }
11615     FOut y = internal::invoke(f, x);
11616     for (std::size_t i = 1; i < n; ++i)
11617     {
11618         y = internal::invoke(f, y);
11619     }
11620     return y;
11621 }
11622 
11623 // API search type: transform_parallelly : ((a -> b), [a]) -> [b]
11624 // fwd bind count: 1
11625 // transform_parallelly((*2), [1, 3, 4]) == [2, 6, 8]
11626 // Same as transform, but can utilize multiple CPUs by using std::launch::async.
11627 // Only makes sense if one run of the provided function
11628 // takes enough time to justify the synchronization overhead.
11629 // One thread per container element is spawned.
11630 // Check out transform_parallelly_n_threads to limit the number of threads.
11631 template <typename F, typename ContainerIn>
transform_parallelly(F f,const ContainerIn & xs)11632 auto transform_parallelly(F f, const ContainerIn& xs)
11633 {
11634     using ContainerOut = typename internal::
11635         same_cont_new_t_from_unary_f<ContainerIn, F, 0>::type;
11636     using X = typename ContainerIn::value_type;
11637     internal::trigger_static_asserts<internal::unary_function_tag, F, X>();
11638     auto handles = transform([&f](const X& x)
11639     {
11640         return std::async(std::launch::async, [&x, &f]()
11641         {
11642             return internal::invoke(f, x);
11643         });
11644     }, xs);
11645 
11646     ContainerOut ys;
11647     internal::prepare_container(ys, size_of_cont(xs));
11648     auto it = internal::get_back_inserter<ContainerOut>(ys);
11649     for (auto& handle : handles)
11650     {
11651         *it = handle.get();
11652     }
11653     return ys;
11654 }
11655 
11656 // API search type: transform_parallelly_n_threads : (Int, (a -> b), [a]) -> [b]
11657 // fwd bind count: 2
11658 // transform_parallelly_n_threads(4, (*2), [1, 3, 4]) == [2, 6, 8]
11659 // Same as transform, but uses n threads in parallel.
11660 // Only makes sense if one run of the provided function
11661 // takes enough time to justify the synchronization overhead.
11662 // Can be used for applying the MapReduce pattern.
11663 template <typename F, typename ContainerIn>
transform_parallelly_n_threads(std::size_t n,F f,const ContainerIn & xs)11664 auto transform_parallelly_n_threads(std::size_t n, F f, const ContainerIn& xs)
11665 {
11666     using ContainerOut = typename internal::
11667         same_cont_new_t_from_unary_f<ContainerIn, F, 0>::type;
11668     using X = typename ContainerIn::value_type;
11669     using Y = internal::invoke_result_t<F, X>;
11670     using x_ptr_t =  const X*;
11671     auto queue = transform_convert<std::vector<x_ptr_t>>(
11672         [](const X& x) -> x_ptr_t
11673         {
11674             return &x;
11675         }, xs);
11676 
11677     std::mutex queue_mutex;
11678     std::mutex thread_results_mutex;
11679     std::map<std::size_t, std::decay_t<Y>> thread_results;
11680     std::size_t queue_idx = 0;
11681 
11682     const auto worker_func = [&]()
11683     {
11684         for (;;)
11685         {
11686             std::size_t idx = std::numeric_limits<std::size_t>::max();
11687             x_ptr_t x_ptr = nullptr;
11688             {
11689                 std::lock_guard<std::mutex> queue_lock(queue_mutex);
11690                 if (queue_idx == queue.size())
11691                 {
11692                     return;
11693                 }
11694                 idx = queue_idx;
11695                 x_ptr = queue[idx];
11696                 ++queue_idx;
11697             }
11698 
11699             const auto y = internal::invoke(f, *x_ptr);
11700 
11701             {
11702                 std::lock_guard<std::mutex> thread_results_lock(
11703                     thread_results_mutex);
11704                 thread_results.insert(std::make_pair(idx, y));
11705             }
11706         }
11707     };
11708 
11709     const auto create_thread = [&]() -> std::thread
11710     {
11711         return std::thread(worker_func);
11712     };
11713     auto threads = generate<std::vector<std::thread>>(create_thread, n);
11714 
11715     for (auto& thread : threads)
11716     {
11717         thread.join();
11718     }
11719 
11720     return get_map_values<decltype(thread_results), ContainerOut>(
11721         thread_results);
11722 }
11723 
11724 // API search type: reduce_parallelly : (((a, a) -> a), a, [a]) -> a
11725 // fwd bind count: 2
11726 // reduce_parallelly((+), 0, [1, 2, 3]) == (0+1+2+3) == 6
11727 // Same as reduce, but can utilize multiple CPUs by using std::launch::async.
11728 // Combines the initial value and all elements of the sequence
11729 // using the given function in unspecified order.
11730 // The set of f, init and value_type should form a commutative monoid.
11731 // One thread per container element is spawned.
11732 // Check out reduce_parallelly_n_threads to limit the number of threads.
11733 template <typename F, typename Container>
reduce_parallelly(F f,const typename Container::value_type & init,const Container & xs)11734 typename Container::value_type reduce_parallelly(
11735     F f, const typename Container::value_type& init, const Container& xs)
11736 {
11737     if (is_empty(xs))
11738     {
11739         return init;
11740     }
11741     else if (size_of_cont(xs) == 1)
11742     {
11743         return internal::invoke(f, init, xs.front());
11744     }
11745     else
11746     {
11747         typedef typename Container::value_type T;
11748         const auto f_on_pair = [f](const std::pair<T, T>& p) -> T
11749         {
11750             return internal::invoke(f, p.first, p.second);
11751         };
11752         auto transform_result =
11753             transform_parallelly(f_on_pair, adjacent_pairs(xs));
11754         if (is_odd(size_of_cont(xs)))
11755         {
11756             transform_result.push_back(last(xs));
11757         }
11758         return reduce_parallelly(f, init, transform_result);
11759     }
11760 }
11761 
11762 // API search type: reduce_parallelly_n_threads : (Int, ((a, a) -> a), a, [a]) -> a
11763 // fwd bind count: 3
11764 // reduce_parallelly_n_threads(2, (+), 0, [1, 2, 3]) == (0+1+2+3) == 6
11765 // Same as reduce, but can utilize multiple CPUs by using std::launch::async.
11766 // Combines the initial value and all elements of the sequence
11767 // using the given function in unspecified order.
11768 // The set of f, init and value_type should form a commutative monoid.
11769 template <typename F, typename Container>
reduce_parallelly_n_threads(std::size_t n,F f,const typename Container::value_type & init,const Container & xs)11770 typename Container::value_type reduce_parallelly_n_threads(
11771     std::size_t n,
11772     F f, const typename Container::value_type& init, const Container& xs)
11773 {
11774     if (is_empty(xs))
11775     {
11776         return init;
11777     }
11778     else if (size_of_cont(xs) == 1)
11779     {
11780         return internal::invoke(f, init, xs.front());
11781     }
11782     else
11783     {
11784         typedef typename Container::value_type T;
11785         const auto f_on_pair = [f](const std::pair<T, T>& p) -> T
11786         {
11787             return internal::invoke(f, p.first, p.second);
11788         };
11789         auto transform_result =
11790             transform_parallelly_n_threads(n, f_on_pair, adjacent_pairs(xs));
11791         if (is_odd(size_of_cont(xs)))
11792         {
11793             transform_result.push_back(last(xs));
11794         }
11795         return reduce_parallelly_n_threads(n, f, init, transform_result);
11796     }
11797 }
11798 
11799 // API search type: reduce_1_parallelly : (((a, a) -> a), [a]) -> a
11800 // fwd bind count: 1
11801 // reduce_1_parallelly((+), [1, 2, 3]) == (1+2+3) == 6
11802 // Same as reduce_1, but can utilize multiple CPUs by using std::launch::async.
11803 // Joins all elements of the sequence using the given function
11804 // in unspecified order.
11805 // The set of f and value_type should form a commutative semigroup.
11806 // One thread per container element is spawned.
11807 // Check out reduce_1_parallelly_n_threads to limit the number of threads.
11808 template <typename F, typename Container>
reduce_1_parallelly(F f,const Container & xs)11809 typename Container::value_type reduce_1_parallelly(F f, const Container& xs)
11810 {
11811     assert(is_not_empty(xs));
11812     if (size_of_cont(xs) == 1)
11813     {
11814         return xs.front();
11815     }
11816     else
11817     {
11818         typedef typename Container::value_type T;
11819         const auto f_on_pair = [f](const std::pair<T, T>& p) -> T
11820         {
11821             return internal::invoke(f, p.first, p.second);
11822         };
11823         auto transform_result =
11824             transform_parallelly(f_on_pair, adjacent_pairs(xs));
11825         if (is_odd(size_of_cont(xs)))
11826         {
11827             transform_result.push_back(last(xs));
11828         }
11829         return reduce_1_parallelly(f, transform_result);
11830     }
11831 }
11832 
11833 // API search type: reduce_1_parallelly_n_threads : (Int, ((a, a) -> a), [a]) -> a
11834 // fwd bind count: 2
11835 // reduce_1_parallelly_n_threads(2, (+), [1, 2, 3]) == (1+2+3) == 6
11836 // Same as reduce_1, but can utilize multiple CPUs by using std::launch::async.
11837 // Joins all elements of the sequence using the given function
11838 // in unspecified order.
11839 // The set of f and value_type should form a commutative semigroup.
11840 template <typename F, typename Container>
reduce_1_parallelly_n_threads(std::size_t n,F f,const Container & xs)11841 typename Container::value_type reduce_1_parallelly_n_threads(
11842     std::size_t n, F f, const Container& xs)
11843 {
11844     assert(is_not_empty(xs));
11845     if (size_of_cont(xs) == 1)
11846     {
11847         return xs.front();
11848     }
11849     else
11850     {
11851         typedef typename Container::value_type T;
11852         const auto f_on_pair = [f](const std::pair<T, T>& p) -> T
11853         {
11854             return internal::invoke(f, p.first, p.second);
11855         };
11856         auto transform_result =
11857             transform_parallelly_n_threads(n, f_on_pair, adjacent_pairs(xs));
11858         if (is_odd(size_of_cont(xs)))
11859         {
11860             transform_result.push_back(last(xs));
11861         }
11862         return reduce_1_parallelly_n_threads(n, f, transform_result);
11863     }
11864 }
11865 
11866 // API search type: keep_if_parallelly : ((a -> Bool), [a]) -> [a]
11867 // fwd bind count: 1
11868 // Same as keep_if but using multiple threads.
11869 // Can be useful if calling the predicate takes some time.
11870 // keep_if_parallelly(is_even, [1, 2, 3, 2, 4, 5]) == [2, 2, 4]
11871 // One thread per container element is spawned.
11872 // Check out keep_if_parallelly_n_threads to limit the number of threads.
11873 template <typename Pred, typename Container>
keep_if_parallelly(Pred pred,const Container & xs)11874 Container keep_if_parallelly(Pred pred, const Container& xs)
11875 {
11876     // Avoid a temporary std::vector<bool>.
11877     const auto idxs = find_all_idxs_by(
11878         is_equal_to<std::uint8_t>(1),
11879         transform_parallelly([pred](const auto & x) -> std::uint8_t {
11880             return pred(x) ? 1 : 0;
11881         }, xs));
11882     return elems_at_idxs(idxs, xs);
11883 }
11884 
11885 // API search type: keep_if_parallelly_n_threads : (Int, (a -> Bool), [a]) -> [a]
11886 // fwd bind count: 2
11887 // Same as keep_if but using multiple threads.
11888 // Can be useful if calling the predicate takes some time.
11889 // keep_if_parallelly_n_threads(3, is_even, [1, 2, 3, 2, 4, 5]) == [2, 2, 4]
11890 template <typename Pred, typename Container>
keep_if_parallelly_n_threads(std::size_t n,Pred pred,const Container & xs)11891 Container keep_if_parallelly_n_threads(
11892     std::size_t n, Pred pred, const Container& xs)
11893 {
11894     // Avoid a temporary std::vector<bool>.
11895     const auto idxs = find_all_idxs_by(
11896         is_equal_to<std::uint8_t>(1),
11897         transform_parallelly_n_threads(n, [pred](const auto & x) -> std::uint8_t {
11898             return pred(x) ? 1 : 0;
11899         }, xs));
11900     return elems_at_idxs(idxs, xs);
11901 }
11902 
11903 // API search type: transform_reduce : ((a -> b), ((b, b) -> b), b, [a]) -> b
11904 // fwd bind count: 3
11905 // transform_reduce(square, add, 0, [1,2,3]) == 0+1+4+9 = 14
11906 // The set of binary_f, init and unary_f::output should form a
11907 // commutative monoid.
11908 template <typename UnaryF, typename BinaryF, typename Container, typename Acc>
transform_reduce(UnaryF unary_f,BinaryF binary_f,const Acc & init,const Container & xs)11909 auto transform_reduce(UnaryF unary_f,
11910                       BinaryF binary_f,
11911                       const Acc& init,
11912                       const Container& xs)
11913 {
11914     return reduce(binary_f, init, transform(unary_f, xs));
11915 }
11916 
11917 // API search type: transform_reduce_1 : ((a -> b), ((b, b) -> b), [a]) -> b
11918 // fwd bind count: 2
11919 // transform_reduce_1(square, add, [1,2,3]) == 0+1+4+9 = 14
11920 // The set of binary_f, and unary_f::output should form
11921 // a commutative semigroup.
11922 template <typename UnaryF, typename BinaryF, typename Container>
transform_reduce_1(UnaryF unary_f,BinaryF binary_f,const Container & xs)11923 auto transform_reduce_1(UnaryF unary_f, BinaryF binary_f, const Container& xs)
11924 {
11925     return reduce_1(binary_f, transform(unary_f, xs));
11926 }
11927 
11928 // API search type: transform_reduce_parallelly : ((a -> b), ((b, b) -> b), b, [a]) -> b
11929 // fwd bind count: 3
11930 // transform_reduce_parallelly(square, add, 0, [1,2,3]) == 0+1+4+9 = 14
11931 // Also known as map_reduce.
11932 // The set of binary_f, init and unary_f::output
11933 // should form a commutative monoid.
11934 // One thread per container element is spawned.
11935 // Check out transform_reduce_parallelly_n_threads to limit the number of threads.
11936 template <typename UnaryF, typename BinaryF, typename Container, typename Acc>
transform_reduce_parallelly(UnaryF unary_f,BinaryF binary_f,const Acc & init,const Container & xs)11937 auto transform_reduce_parallelly(UnaryF unary_f,
11938                                  BinaryF binary_f,
11939                                  const Acc& init,
11940                                  const Container& xs)
11941 {
11942     return reduce_parallelly(binary_f, init, transform_parallelly(unary_f, xs));
11943 }
11944 
11945 // API search type: transform_reduce_parallelly_n_threads : (Int, (a -> b), ((b, b) -> b), b, [a]) -> b
11946 // fwd bind count: 4
11947 // transform_reduce_parallelly_n_threads(2, square, add, 0, [1,2,3]) == 0+1+4+9 = 14
11948 // Also known as map_reduce.
11949 // The set of binary_f, init and unary_f::output
11950 // should form a commutative monoid.
11951 template <typename UnaryF, typename BinaryF, typename Container, typename Acc>
transform_reduce_parallelly_n_threads(std::size_t n,UnaryF unary_f,BinaryF binary_f,const Acc & init,const Container & xs)11952 auto transform_reduce_parallelly_n_threads(std::size_t n,
11953                                            UnaryF unary_f,
11954                                            BinaryF binary_f,
11955                                            const Acc& init,
11956                                            const Container& xs)
11957 {
11958     return reduce_parallelly_n_threads(
11959         n, binary_f, init, transform_parallelly_n_threads(n, unary_f, xs));
11960 }
11961 
11962 // API search type: transform_reduce_1_parallelly : ((a -> b), ((b, b) -> b), [a]) -> b
11963 // fwd bind count: 2
11964 // transform_reduce_1_parallelly(square, add, [1,2,3]) == 0+1+4+9 = 14
11965 // Also Known as map_reduce.
11966 // The set of binary_f, and unary_f::output
11967 // should form a commutative semigroup.
11968 // One thread per container element is spawned.
11969 // Check out transform_reduce_1_parallelly_n_threads to limit the number of threads.
11970 template <typename UnaryF, typename BinaryF, typename Container>
transform_reduce_1_parallelly(UnaryF unary_f,BinaryF binary_f,const Container & xs)11971 auto transform_reduce_1_parallelly(UnaryF unary_f,
11972                                    BinaryF binary_f,
11973                                    const Container& xs)
11974 {
11975     return reduce_1_parallelly(binary_f, transform_parallelly(unary_f, xs));
11976 }
11977 
11978 // API search type: transform_reduce_1_parallelly_n_threads : (Int, (a -> b), ((b, b) -> b), [a]) -> b
11979 // fwd bind count: 3
11980 // transform_reduce_1_parallelly_n_threads(2, square, add, [1,2,3]) == 0+1+4+9 = 14
11981 // Also Known as map_reduce.
11982 // The set of binary_f, and unary_f::output
11983 // should form a commutative semigroup.
11984 template <typename UnaryF, typename BinaryF, typename Container>
transform_reduce_1_parallelly_n_threads(std::size_t n,UnaryF unary_f,BinaryF binary_f,const Container & xs)11985 auto transform_reduce_1_parallelly_n_threads(std::size_t n,
11986                                              UnaryF unary_f,
11987                                              BinaryF binary_f,
11988                                              const Container& xs)
11989 {
11990     return reduce_1_parallelly_n_threads(
11991         n, binary_f, transform_parallelly_n_threads(n, unary_f, xs));
11992 }
11993 
11994 } // namespace fplus
11995 #include <array>
11996 #include <chrono>
11997 #include <functional>
11998 
11999 namespace fplus
12000 {
12001 
12002 // Optimizes the initial position to the nearest local minimum
12003 // in regards to the objective_function
12004 // using numerical gradient descent based on the epsilon neighborhood.
12005 // momentum_conservation should be in [0, 1). A low value means much decay.
12006 // If no fixed step size is provided, each step advances by the length
12007 // of the gradient.
12008 // In both cases the step is scaled with a step factor, starting at 1.0.
12009 // If one iteration results in no further improvement,
12010 // the step factor is reduced by a factor of 0.5.
12011 // The callback is executed with
12012 // iteration, step factor, momentum and current position
12013 // after every iteration.
12014 // A initial step factor other than 1.0 in all dimensions
12015 // can be emulated by scaling ones objective function accordingly.
12016 // Optimization stops if one of the provided criteria is met.
12017 // minimize_downhill<1>(\x -> square(x[0] + 2), 0.0001, 0.01, {123})[0] == -2;
12018 template <std::size_t N, typename F, typename pos_t = std::array<double, N>>
minimize_downhill(F objective_function,double epsilon,const pos_t & init_pos,maybe<double> fixed_step_size=nothing<double> (),double momentum_conservation=0.5,double sufficing_value=std::numeric_limits<double>::lowest (),double min_step_factor=std::numeric_limits<double>::min (),std::size_t max_iterations=std::numeric_limits<std::size_t>::max (),long int max_milliseconds=std::numeric_limits<long int>::max (),const std::function<void (std::size_t,double,const pos_t &,const pos_t &)> & callback=std::function<void (std::size_t,double,const pos_t &,const pos_t &)> ())12019 pos_t minimize_downhill(
12020         F objective_function,
12021         double epsilon,
12022         const pos_t& init_pos,
12023         maybe<double> fixed_step_size = nothing<double>(),
12024         double momentum_conservation = 0.5,
12025         double sufficing_value = std::numeric_limits<double>::lowest(),
12026         double min_step_factor = std::numeric_limits<double>::min(),
12027         std::size_t max_iterations = std::numeric_limits<std::size_t>::max(),
12028         long int max_milliseconds = std::numeric_limits<long int>::max(),
12029         const std::function<
12030                 void (std::size_t, double, const pos_t&, const pos_t&)>&
12031             callback =
12032             std::function<
12033                 void (std::size_t, double, const pos_t&, const pos_t&)>())
12034 {
12035     std::size_t iteration = 0;
12036     double step_factor = 1.0;
12037     pos_t position = init_pos;
12038     double value = internal::invoke(objective_function, position);
12039 
12040     const auto start_time = std::chrono::steady_clock::now();
12041     const auto is_done = [&]() -> bool
12042     {
12043         if (max_milliseconds != std::numeric_limits<long int>::max())
12044         {
12045             const auto current_time = std::chrono::steady_clock::now();
12046             const auto elapsed = current_time - start_time;
12047             const auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
12048             if (elapsed_ms >= max_milliseconds)
12049             {
12050                 return true;
12051             }
12052         }
12053         return
12054             iteration >= max_iterations ||
12055             step_factor <= min_step_factor ||
12056             value <= sufficing_value;
12057     };
12058 
12059     const auto calc_gradient =
12060         [&](const pos_t& pos) -> pos_t
12061     {
12062         pos_t result;
12063         for (std::size_t dim = 0; dim < N; ++dim)
12064         {
12065             auto test_pos_1 = pos;
12066             auto test_pos_2 = pos;
12067             test_pos_1[dim] -= epsilon / 2.0;
12068             test_pos_2[dim] += epsilon / 2.0;
12069             const auto val_1 = internal::invoke(objective_function, test_pos_1);
12070             const auto val_2 = internal::invoke(objective_function, test_pos_2);
12071             result[dim] = (val_2 - val_1) / epsilon;
12072         }
12073         return result;
12074     };
12075 
12076     const auto add = [](const pos_t& p1, const pos_t& p2) -> pos_t
12077     {
12078         pos_t result;
12079         for (std::size_t dim = 0; dim < N; ++dim)
12080         {
12081             result[dim] = p1[dim] + p2[dim];
12082         }
12083         return result;
12084     };
12085 
12086     const auto multiply = [](const pos_t& p, double f) -> pos_t
12087     {
12088         pos_t result;
12089         for (std::size_t dim = 0; dim < N; ++dim)
12090         {
12091             result[dim] = p[dim] * f;
12092         }
12093         return result;
12094     };
12095 
12096     const auto dist_to_origin = [](const pos_t& p) -> double
12097     {
12098         double acc = 0;
12099         for (std::size_t dim = 0; dim < N; ++dim)
12100         {
12101             acc += square(p[dim]);
12102         }
12103         return sqrt(acc);
12104     };
12105 
12106     const auto normalize = [&](const pos_t& p) -> pos_t
12107     {
12108         return multiply(p, 1.0 / dist_to_origin(p));
12109     };
12110 
12111     const auto null_vector = []() -> pos_t
12112     {
12113         pos_t result;
12114         for (std::size_t dim = 0; dim < N; ++dim)
12115         {
12116             result[dim] = 0;
12117         }
12118         return result;
12119     };
12120 
12121     pos_t momentum = null_vector();
12122     while (!is_done())
12123     {
12124         auto new_momentum = multiply(momentum, momentum_conservation);
12125         pos_t gradient = calc_gradient(add(position, new_momentum));
12126         const auto inverse_gradient = multiply(gradient, -1.0);
12127 
12128         auto new_momentum_add =
12129             is_nothing(fixed_step_size) ?
12130                 inverse_gradient :
12131                 multiply(
12132                     normalize(inverse_gradient),
12133                     fixed_step_size.unsafe_get_just());
12134 
12135         new_momentum =
12136             multiply(
12137                 add(new_momentum, new_momentum_add),
12138                 step_factor);
12139         if (dist_to_origin(momentum) <= std::numeric_limits<double>::min() &&
12140             dist_to_origin(new_momentum) <= std::numeric_limits<double>::min())
12141         {
12142             break;
12143         }
12144         const auto new_position = add(position, new_momentum);
12145         const auto new_value = internal::invoke(objective_function, new_position);
12146         if (new_value >= value)
12147         {
12148             step_factor /= 2.0;
12149         }
12150         else
12151         {
12152             value = new_value;
12153             position = new_position;
12154             momentum = new_momentum;
12155         }
12156         ++iteration;
12157         if (callback)
12158         {
12159             callback(iteration, step_factor, momentum, position);
12160         }
12161     }
12162     return position;
12163 }
12164 
12165 } // namespace fplus
12166 
12167 //
12168 // queue.hpp
12169 //
12170 
12171 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
12172 // https://github.com/Dobiasd/FunctionalPlus
12173 // Distributed under the Boost Software License, Version 1.0.
12174 // (See accompanying file LICENSE_1_0.txt or copy at
12175 //  http://www.boost.org/LICENSE_1_0.txt)
12176 
12177 
12178 
12179 #include <condition_variable>
12180 #include <cstdint>
12181 #include <deque>
12182 #include <mutex>
12183 
12184 namespace fplus
12185 {
12186 
12187 // A thread-safe queue.
12188 template <typename T>
12189 class queue
12190 {
12191 public:
queue()12192     queue() :
12193         queue_(),
12194         mutex_(),
12195         cond_()
12196         {}
pop()12197     fplus::maybe<T> pop()
12198     {
12199         std::unique_lock<std::mutex> lock(mutex_);
12200         if (queue_.empty())
12201         {
12202             return {};
12203         }
12204         auto item = queue_.front();
12205         queue_.pop_front();
12206         return item;
12207     }
12208 
push(const T & item)12209     void push(const T& item)
12210     {
12211         {
12212             std::unique_lock<std::mutex> lock(mutex_);
12213             queue_.push_back(item);
12214         }
12215         cond_.notify_one();
12216     }
12217 
pop_all()12218     std::vector<T> pop_all()
12219     {
12220         std::unique_lock<std::mutex> mlock(mutex_);
12221         const auto result = fplus::convert_container<std::vector<T>>(queue_);
12222         queue_.clear();
12223         return result;
12224     }
12225 
wait_and_pop_all()12226     std::vector<T> wait_and_pop_all()
12227     {
12228         std::unique_lock<std::mutex> mlock(mutex_);
12229         cond_.wait(mlock, [&]() -> bool { return !queue_.empty(); });
12230         const auto result = fplus::convert_container<std::vector<T>>(queue_);
12231         queue_.clear();
12232         return result;
12233     }
12234 
wait_for_and_pop_all(std::int64_t max_wait_time_us)12235     std::vector<T> wait_for_and_pop_all(std::int64_t max_wait_time_us)
12236     {
12237         std::unique_lock<std::mutex> mlock(mutex_);
12238         const auto t = std::chrono::microseconds{ max_wait_time_us };
12239         cond_.wait_for(mlock, t, [&]() -> bool { return !queue_.empty(); });
12240         const auto result = fplus::convert_container<std::vector<T>>(queue_);
12241         queue_.clear();
12242         return result;
12243     }
12244 
12245 private:
12246     std::deque<T> queue_;
12247     std::mutex mutex_;
12248     std::condition_variable cond_;
12249 };
12250 
12251 } // namespace fplus
12252 
12253 //
12254 // raii.hpp
12255 //
12256 
12257 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
12258 // https://github.com/Dobiasd/FunctionalPlus
12259 // Distributed under the Boost Software License, Version 1.0.
12260 // (See accompanying file LICENSE_1_0.txt or copy at
12261 //  http://www.boost.org/LICENSE_1_0.txt)
12262 
12263 
12264 
12265 //
12266 // shared_ref.hpp
12267 //
12268 
12269 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
12270 // https://github.com/Dobiasd/FunctionalPlus
12271 // Distributed under the Boost Software License, Version 1.0.
12272 // (See accompanying file LICENSE_1_0.txt or copy at
12273 //  http://www.boost.org/LICENSE_1_0.txt)
12274 
12275 
12276 #include <memory>
12277 
12278 namespace fplus
12279 {
12280 
12281 // A std::shared_ptr expresses
12282 // optionality of the contained value (can be nullptr)
12283 // and shared ownership that can be transferred.
12284 // A std::optional expresses optionality only.
12285 // The standard does not provide a class to
12286 // express only shared ownership without optionality.
12287 // shared_ref fills this gap.
12288 // It is recommended to use make_shared_ref for constructing an instance.
12289 template <typename T>
12290 class shared_ref
12291 {
12292 public:
12293     shared_ref(const shared_ref&) = default;
12294     shared_ref(shared_ref&&) = default;
12295     shared_ref& operator=(const shared_ref&) = default;
12296     shared_ref& operator=(shared_ref&&) = default;
12297     ~shared_ref() = default;
12298 
operator ->()12299     T* operator->() { return m_ptr.get(); }
operator ->() const12300     const T* operator->() const { return m_ptr.get(); }
12301 
operator *()12302     T& operator*() { return *m_ptr.get(); }
operator *() const12303     const T& operator*() const { return *m_ptr.get(); }
12304 
12305     template <typename XT, typename...XTypes>
12306     friend shared_ref<XT> make_shared_ref(XTypes&&...args);
12307 
12308 private:
12309     std::shared_ptr<T> m_ptr;
shared_ref(T * value)12310     shared_ref(T* value) :m_ptr(value) { assert(value != nullptr);  }
12311 };
12312 
12313 // http://stackoverflow.com/a/41976419/1866775
12314 template <typename T, typename...Types>
make_shared_ref(Types &&...args)12315 shared_ref<T> make_shared_ref(Types&&...args)
12316 {
12317     return shared_ref<T>(new T(std::forward<Types>(args)...));
12318 }
12319 
12320 } // namespace fplus
12321 
12322 namespace fplus
12323 {
12324 
12325 // A generic RAII class.
12326 // It is recommended to use make_raii for constructing an instance.
12327 template <typename INIT, typename QUIT>
12328 class raii
12329 {
12330 public:
raii(INIT init,QUIT quit)12331     raii(INIT init, QUIT quit) :
12332         quit_(quit)
12333     {
12334         init();
12335     }
~raii()12336     ~raii()
12337     {
12338         quit_();
12339     }
12340     raii(const raii&) = delete;
12341     raii(raii&&) = default;
12342     raii& operator=(const raii&) = delete;
12343     raii& operator=(raii&&) = default;
12344 private:
12345     QUIT quit_;
12346 };
12347 
12348 template <typename INIT, typename QUIT>
make_raii(INIT init,QUIT quit)12349 shared_ref<raii<INIT, QUIT>> make_raii(INIT init, QUIT quit)
12350 {
12351     return make_shared_ref<raii<INIT, QUIT>>(init, quit);
12352 }
12353 
12354 
12355 } // namespace fplus
12356 
12357 //
12358 // read.hpp
12359 //
12360 
12361 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
12362 // https://github.com/Dobiasd/FunctionalPlus
12363 // Distributed under the Boost Software License, Version 1.0.
12364 // (See accompanying file LICENSE_1_0.txt or copy at
12365 //  http://www.boost.org/LICENSE_1_0.txt)
12366 
12367 
12368 
12369 #include <string>
12370 #include <type_traits>
12371 
12372 namespace fplus
12373 {
12374 
12375 namespace internal
12376 {
12377     template <typename T>
12378     struct helper_read_value_struct {};
12379 
12380     template <>
12381     struct helper_read_value_struct <int>
12382     {
readfplus::internal::helper_read_value_struct12383         static void read(const std::string& str,
12384             int& result, std::size_t& num_chars_used)
12385         {
12386             result = std::stoi(str, &num_chars_used);
12387         }
12388     };
12389 
12390     template <>
12391     struct helper_read_value_struct <long>
12392     {
readfplus::internal::helper_read_value_struct12393         static void read(const std::string& str,
12394             long& result, std::size_t& num_chars_used)
12395         {
12396             result = std::stol(str, &num_chars_used);
12397         }
12398     };
12399 
12400     template <>
12401     struct helper_read_value_struct <long long>
12402     {
readfplus::internal::helper_read_value_struct12403         static void read(const std::string& str,
12404             long long& result, std::size_t& num_chars_used)
12405         {
12406             result = std::stoll(str, &num_chars_used);
12407         }
12408     };
12409 
12410     template <>
12411     struct helper_read_value_struct <unsigned int>
12412     {
readfplus::internal::helper_read_value_struct12413         static void read(const std::string& str,
12414             unsigned int& result, std::size_t& num_chars_used)
12415         {
12416             unsigned long result_u_l = std::stoul(str, &num_chars_used);
12417             result = static_cast<unsigned int>(result_u_l);
12418         }
12419     };
12420 
12421     template <>
12422     struct helper_read_value_struct <unsigned long>
12423     {
readfplus::internal::helper_read_value_struct12424         static void read(const std::string& str,
12425             unsigned long& result, std::size_t& num_chars_used)
12426         {
12427             result = std::stoul(str, &num_chars_used);
12428         }
12429     };
12430 
12431     template <>
12432     struct helper_read_value_struct <unsigned long long>
12433     {
readfplus::internal::helper_read_value_struct12434         static void read(const std::string& str,
12435             unsigned long long& result, std::size_t& num_chars_used)
12436         {
12437             result = std::stoull(str, &num_chars_used);
12438         }
12439     };
12440 
12441     template <>
12442     struct helper_read_value_struct <float>
12443     {
readfplus::internal::helper_read_value_struct12444         static void read(const std::string& str,
12445             float& result, std::size_t& num_chars_used)
12446         {
12447             result = std::stof(str, &num_chars_used);
12448         }
12449     };
12450 
12451     template <>
12452     struct helper_read_value_struct <double>
12453     {
readfplus::internal::helper_read_value_struct12454         static void read(const std::string& str,
12455             double& result, std::size_t& num_chars_used)
12456         {
12457             result = std::stod(str, &num_chars_used);
12458         }
12459     };
12460 
12461     template <>
12462     struct helper_read_value_struct <long double>
12463     {
readfplus::internal::helper_read_value_struct12464         static void read(const std::string& str,
12465             long double& result, std::size_t& num_chars_used)
12466         {
12467             result = std::stold(str, &num_chars_used);
12468         }
12469     };
12470 
12471     template <>
12472     struct helper_read_value_struct <std::string>
12473     {
readfplus::internal::helper_read_value_struct12474         static void read(const std::string& str,
12475             std::string& result, std::size_t& num_chars_used)
12476         {
12477             num_chars_used = str.size();
12478             result = str;
12479         }
12480     };
12481 }
12482 
12483 // API search type: read_value_result : String -> Result a
12484 // Try to deserialize a value.
12485 template <typename T>
read_value_result(const std::string & str)12486 result<T, std::string> read_value_result(const std::string& str)
12487 {
12488     try
12489     {
12490         T result;
12491         std::size_t num_chars_used = 0;
12492         internal::helper_read_value_struct<T>::read(str,
12493             result, num_chars_used);
12494         if (num_chars_used != str.size())
12495         {
12496             return error<T>(std::string("String not fully parsable."));
12497         }
12498         return ok<T, std::string>(result);
12499     } catch(const std::invalid_argument& e) {
12500         return error<T, std::string>(e.what());
12501     } catch(const std::out_of_range& e) {
12502         return error<T, std::string>(e.what());
12503     }
12504 }
12505 
12506 // API search type: read_value : String -> Maybe a
12507 // Try to deserialize/parse a value, e.g.:
12508 // String to Int
12509 // String to Float
12510 // String to Double
12511 // read_value<unsigned int>("42") == 42
12512 // etc.
12513 template <typename T>
read_value(const std::string & str)12514 maybe<T> read_value(const std::string& str)
12515 {
12516     return to_maybe(read_value_result<T>(str));
12517 }
12518 
12519 // API search type: read_value_with_default : (a, String) -> a
12520 // fwd bind count: 1
12521 // Try to deserialize a value, return given default on failure, e.g.:
12522 // String to Int
12523 // String to Float
12524 // String to Double
12525 // read_value_with_default<unsigned int>(3, "42") == 42
12526 // read_value_with_default<unsigned int>(3, "") == 3
12527 // read_value_with_default<unsigned int>(3, "foo") == 3
12528 // etc.
12529 template <typename T>
read_value_with_default(const T & def,const std::string & str)12530 T read_value_with_default(const T& def, const std::string& str)
12531 {
12532     return just_with_default(def, to_maybe(read_value_result<T>(str)));
12533 }
12534 
12535 // API search type: read_value_unsafe : String -> a
12536 // Try to deserialize a value, crash on failure, e.g.:
12537 // String to Int
12538 // String to Float
12539 // String to Double
12540 // read_value_unsafe<unsigned int>("42") == 42
12541 // read_value_unsafe<unsigned int>("") == crash
12542 // read_value_unsafe<unsigned int>("foo") == crash
12543 // See read_value and read_value_with_default for safe versions.
12544 // etc.
12545 template <typename T>
read_value_unsafe(const std::string & str)12546 T read_value_unsafe(const std::string& str)
12547 {
12548     return unsafe_get_just(to_maybe(read_value_result<T>(str)));
12549 }
12550 
12551 } // namespace fplus
12552 
12553 //
12554 // replace.hpp
12555 //
12556 
12557 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
12558 // https://github.com/Dobiasd/FunctionalPlus
12559 // Distributed under the Boost Software License, Version 1.0.
12560 // (See accompanying file LICENSE_1_0.txt or copy at
12561 //  http://www.boost.org/LICENSE_1_0.txt)
12562 
12563 
12564 
12565 namespace fplus
12566 {
12567 
12568 namespace internal
12569 {
12570 
12571 template <typename UnaryPredicate, typename T, typename Container>
replace_if(internal::reuse_container_t,UnaryPredicate p,const T & dest,Container && xs)12572 Container replace_if(internal::reuse_container_t,
12573     UnaryPredicate p, const T& dest, Container&& xs)
12574 {
12575     std::replace_if(std::begin(xs), std::end(xs), p, dest);
12576     return std::forward<Container>(xs);
12577 }
12578 
12579 template <typename UnaryPredicate, typename T, typename Container>
replace_if(internal::create_new_container_t,UnaryPredicate p,const T & dest,const Container & xs)12580 Container replace_if(internal::create_new_container_t,
12581     UnaryPredicate p, const T& dest, const Container& xs)
12582 {
12583     Container ys = xs;
12584     return replace_if(internal::reuse_container_t(),
12585         p, dest, std::move(ys));
12586 }
12587 
12588 } // namespace internal
12589 
12590 // API search type: replace_if : ((a -> Bool), a, [a]) -> [a]
12591 // fwd bind count: 2
12592 // Replace every element fulfilling a predicate with a specific value.
12593 // replace_if(is_even, 0, [1, 3, 4, 6, 7]) == [1, 3, 0, 0, 7]
12594 template <typename UnaryPredicate, typename Container,
12595     typename ContainerOut = internal::remove_const_and_ref_t<Container>>
replace_if(UnaryPredicate p,const typename ContainerOut::value_type & dest,Container && xs)12596 ContainerOut replace_if(UnaryPredicate p,
12597     const typename ContainerOut::value_type& dest, Container&& xs)
12598 {
12599     return internal::replace_if(internal::can_reuse_v<Container>{},
12600         p, dest, std::forward<Container>(xs));
12601 }
12602 
12603 namespace internal
12604 {
12605 
12606 template <typename Container,
12607         typename T = typename Container::value_type>
12608 Container replace_elem_at_idx(internal::reuse_container_t,
12609     std::size_t idx, const T& dest, Container&& xs)
12610 {
12611     assert(idx < xs.size());
12612     auto it = std::begin(xs);
12613     advance_iterator(it, idx);
12614     *it = dest;
12615     return std::forward<Container>(xs);
12616 }
12617 
12618 template <typename Container,
12619         typename T = typename Container::value_type>
12620 Container replace_elem_at_idx(internal::create_new_container_t,
12621     std::size_t idx, const T& dest, const Container& xs)
12622 {
12623     Container ys = xs;
12624     return replace_elem_at_idx(internal::reuse_container_t(),
12625         idx, dest, std::move(ys));
12626 }
12627 
12628 } // namespace internal
12629 
12630 // API search type: replace_elem_at_idx : (Int, a, [a]) -> [a]
12631 // fwd bind count: 2
12632 // Replace the element at a specific index.
12633 // replace_elem_at_idx(2, 0, [1, 3, 4, 4, 7]) == [1, 3, 0, 4, 7]
12634 template <typename Container,
12635         typename ContainerOut = internal::remove_const_and_ref_t<Container>,
12636         typename T = typename ContainerOut::value_type>
12637 ContainerOut replace_elem_at_idx(std::size_t idx, const T& dest,
12638     Container&& xs)
12639 {
12640     return internal::replace_elem_at_idx(internal::can_reuse_v<Container>{},
12641         idx, dest, std::forward<Container>(xs));
12642 }
12643 
12644 // API search type: replace_elems : (a, a, [a]) -> [a]
12645 // fwd bind count: 2
12646 // Replace all elements matching source with dest.
12647 // replace_elems(4, 0, [1, 3, 4, 4, 7]) == [1, 3, 0, 0, 7]
12648 template <typename Container,
12649         typename ContainerOut = internal::remove_const_and_ref_t<Container>,
12650         typename T = typename ContainerOut::value_type>
12651 ContainerOut replace_elems(const T& source, const T& dest, Container&& xs)
12652 {
12653     return replace_if(bind_1st_of_2(is_equal<T>, source), dest, xs);
12654 }
12655 
12656 // API search type: replace_tokens : ([a], [a], [a]) -> [a]
12657 // fwd bind count: 2
12658 // Replace all segments matching source with dest.
12659 // replace_tokens("haha", "hihi", "oh, hahaha!") == "oh, hihiha!"
12660 // replace_tokens("haha", "o", "oh, hahaha!") == "oh, oha!"
12661 template <typename Container>
replace_tokens(const Container & source,const Container & dest,const Container & xs)12662 Container replace_tokens
12663         (const Container& source, const Container& dest, const Container& xs)
12664 {
12665     auto splitted = split_by_token(source, true, xs);
12666     return join(dest, splitted);
12667 }
12668 
12669 } // namespace fplus
12670 
12671 //
12672 // show.hpp
12673 //
12674 
12675 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
12676 // https://github.com/Dobiasd/FunctionalPlus
12677 // Distributed under the Boost Software License, Version 1.0.
12678 // (See accompanying file LICENSE_1_0.txt or copy at
12679 //  http://www.boost.org/LICENSE_1_0.txt)
12680 
12681 
12682 
12683 #include <iomanip>
12684 #include <ios>
12685 #include <sstream>
12686 #include <string>
12687 
12688 namespace fplus
12689 {
12690 
12691 // API search type: show : a -> String
12692 // fwd bind count: 0
12693 // 42 -> "42"
12694 // Useful to simply show values, e.g.:
12695 // Int to String
12696 // Float to String
12697 // Double to String
12698 // Pair to String
12699 // std::vector<std::list<T>> to String
12700 // std::vector<T> to String
12701 template <typename T>
show(const T & x)12702 std::string show(const T& x)
12703 {
12704     std::ostringstream ss;
12705     ss << x;
12706     return ss.str();
12707 }
12708 
12709 // string identity
12710 // "foo" -> "foo"
12711 inline
show(const std::string & str)12712 std::string show(const std::string& str)
12713 {
12714     return str;
12715 }
12716 
12717 template <typename T, typename A>
12718 std::string show(const std::vector<T, A>& xs);
12719 
12720 template <typename T, typename A>
12721 std::string show(const std::list<T, A>& xs);
12722 
12723 // {1, "one"} -> "(1, one)"
12724 template <typename X, typename Y>
show(const std::pair<X,Y> & p)12725 std::string show(const std::pair<X, Y>& p)
12726 {
12727     return std::string("(") + show(p.first) + ", " + show(p.second) + ")";
12728 }
12729 
12730 template <typename Container> std::string show_cont(const Container& xs);
12731 
12732 template <typename T, typename A>
show(const std::vector<T,A> & xs)12733 std::string show(const std::vector<T, A>& xs)
12734 {
12735     return show_cont(xs);
12736 }
12737 
12738 template <typename T, typename A>
show(const std::list<T,A> & xs)12739 std::string show(const std::list<T, A>& xs)
12740 {
12741     return show_cont(xs);
12742 }
12743 
12744 template <typename T, typename A>
show(const std::set<T,A> & xs)12745 std::string show(const std::set<T, A>& xs)
12746 {
12747     return show_cont(xs);
12748 }
12749 
12750 template <typename T, typename A>
show(const std::deque<T,A> & xs)12751 std::string show(const std::deque<T, A>& xs)
12752 {
12753     return show_cont(xs);
12754 }
12755 
12756 // API search type: show_cont_with_frame_and_newlines : (String, String, String, [a], Int) -> String
12757 // fwd bind count: 3
12758 // show_cont_with_frame_and_newlines (",", "(", ")", [1, 2, 3, 4, 5], 2)
12759 // == "(1,2)
12760 //      3,4)
12761 //      5)"
12762 template <typename Container>
show_cont_with_frame_and_newlines(const std::string & separator,const std::string & prefix,const std::string & suffix,const Container & xs,std::size_t new_line_every_nth_elem)12763 std::string show_cont_with_frame_and_newlines(
12764     const std::string& separator,
12765     const std::string& prefix, const std::string& suffix,
12766     const Container& xs,
12767     std::size_t new_line_every_nth_elem )
12768 {
12769     std::vector<std::string> elemStrs;
12770     elemStrs.reserve(xs.size());
12771     if (new_line_every_nth_elem == 0)
12772     {
12773         for (const auto& x : xs)
12774         {
12775             elemStrs.push_back(show(x));
12776         }
12777     }
12778     else
12779     {
12780         std::size_t i = 0;
12781         std::string newline =
12782             std::string("\n") + std::string(prefix.size(), ' ');
12783         for (const auto& x : xs)
12784         {
12785             if ( i && i % new_line_every_nth_elem == 0)
12786                 elemStrs.push_back(newline + show(x));
12787             else
12788                 elemStrs.push_back(show(x));
12789             ++i;
12790         }
12791     }
12792     return prefix + join(separator, elemStrs) + suffix;
12793 }
12794 
12795 // API search type: show_cont_with_frame : (String, String, String, [a]) -> String
12796 // fwd bind count: 3
12797 // show_cont_with_frame (" => ", "{", "}", [1, 2, 3]) == "{1 => 2 => 3}"
12798 template <typename Container>
show_cont_with_frame(const std::string & separator,const std::string & prefix,const std::string & suffix,const Container & xs)12799 std::string show_cont_with_frame(
12800     const std::string& separator,
12801     const std::string& prefix, const std::string& suffix,
12802     const Container& xs)
12803 {
12804     return
12805         show_cont_with_frame_and_newlines( separator, prefix, suffix, xs, 0);
12806 }
12807 
12808 // API search type: show_cont_with : (String, [a]) -> String
12809 // fwd bind count: 1
12810 // show_cont_with( " - ", [1, 2, 3]) == "[1 - 2 - 3]"
12811 template <typename Container>
show_cont_with(const std::string & separator,const Container & xs)12812 std::string show_cont_with(const std::string& separator, const Container& xs)
12813 {
12814     return show_cont_with_frame(separator, "[", "]", xs);
12815 }
12816 
12817 // API search type: show_cont : [a] -> String
12818 // fwd bind count: 0
12819 // show_cont [1, 2, 3] -> "[1, 2, 3]"
12820 // Can i.a show std::vector and std::map.
12821 template <typename Container>
show_cont(const Container & xs)12822 std::string show_cont(const Container& xs)
12823 {
12824     return show_cont_with(", ", xs);
12825 }
12826 
12827 // API search type: show_maybe : Maybe a -> String
12828 // fwd bind count: 0
12829 // show_maybe(Just 42) -> "Just 42"
12830 template <typename T>
show_maybe(const maybe<T> & maybe)12831 std::string show_maybe(const maybe<T>& maybe)
12832 {
12833     if (is_nothing(maybe))
12834         return "Nothing";
12835     else
12836         return std::string("Just " + show(unsafe_get_just(maybe)));
12837 }
12838 
12839 // API search type: show_result : Result a b -> String
12840 // fwd bind count: 0
12841 // show_result(Ok 42) -> "Ok 42"
12842 // show_result(Error "fail") -> "Error fail"
12843 template <typename Ok, typename Error>
show_result(const result<Ok,Error> & result)12844 std::string show_result(const result<Ok, Error>& result)
12845 {
12846     if (is_error(result))
12847         return std::string("Error " + show(unsafe_get_error(result)));
12848     else
12849         return std::string("Ok " + show(unsafe_get_ok(result)));
12850 }
12851 
12852 // API search type: show_float : (Int, Int, Float) -> String
12853 // fwd bind count: 2
12854 // Can be used to show floating point values in a specific format
12855 // (Float to String, Double to String etc.)
12856 // Examples:
12857 // const double pi = 3.14159
12858 // show_float<double>(0, 3, pi) == "3.142"
12859 // show_float<double>(1, 3, pi) == "3.142"
12860 // show_float<double>(2, 3, pi) == "03.142"
12861 // show_float<double>(3, 3, pi) == "003.142"
12862 // show_float<double>(1, 2, pi) == "3.14"
12863 // show_float<double>(1, 4, pi) == "3.1416"
12864 // show_float<double>(1, 7, pi) == "3.1415900"
12865 // show_float<double>(0, 3, -pi) == "-3.142"
12866 // show_float<double>(1, 3, -pi) == "-3.142"
12867 // show_float<double>(2, 3, -pi) == "-3.142"
12868 // show_float<double>(3, 3, -pi) == "-03.142"
12869 // show_float<double>(4, 3, -pi) == "-003.142"
12870 // show_float<double>(0, 3, 0.142) == "0.142";
12871 // show_float<double>(1, 3, 0.142) == "0.142";
12872 // show_float<double>(2, 3, 0.142) == "00.142";
12873 // fill_left(8, ' ', show_float<double>(0, 3, -pi)) == "  -3.142"
12874 template <typename T>
show_float(std::size_t min_left_chars,std::size_t right_char_count,const T & x)12875 std::string show_float(
12876     std::size_t min_left_chars, std::size_t right_char_count, const T& x)
12877 {
12878     bool is_negative = x < 0;
12879     std::size_t min_left_chars_final =
12880         is_negative && min_left_chars > 0
12881         ? min_left_chars - 1
12882         : min_left_chars;
12883     std::stringstream stream;
12884     stream
12885         << std::fixed
12886         << std::setprecision(static_cast<int>(right_char_count))
12887         << std::abs(x);
12888     std::string s = stream.str();
12889     std::size_t min_dest_length = min_left_chars_final + 1 + right_char_count;
12890     std::string result = fill_left('0', min_dest_length, s);
12891     if (is_negative)
12892     {
12893         result = std::string("-") + result;
12894     }
12895     return result;
12896 }
12897 
12898 // API search type: show_float_fill_left : (Char, Int, Int, Float) -> String
12899 // fwd bind count: 3
12900 // Can be used to show floating point values in a specific precision
12901 // left-padded with some character.
12902 // (Float to String, Double to String etc.)
12903 // Examples:
12904 // const double pi = 3.14159
12905 // show_float_fill_left<double>(' ', 8, 3, pi) == "   3.142"
12906 // show_float_fill_left<double>(' ', 8, 6, pi) == "3.141590"
12907 // show_float_fill_left<double>(' ', 8, 3, -pi) == "  -3.142"
12908 // show_float_fill_left<double>(' ', 2, 3, -pi) == "-3.142"
12909 template <typename T>
show_float_fill_left(const std::string::value_type & filler,std::size_t min_size,std::size_t right_char_count,const T & x)12910 std::string show_float_fill_left(const std::string::value_type& filler,
12911         std::size_t min_size, std::size_t right_char_count, const T& x)
12912 {
12913     return fill_left(filler, min_size, show_float<T>(0, right_char_count, x));
12914 }
12915 
12916 // API search type: show_fill_left : (Char, Int, a) -> String
12917 // fwd bind count: 2
12918 // Convert some value to a string with left-padded with some character.
12919 // (Int to String etc.)
12920 // Examples:
12921 // show_fill_left<int>(' ', 4, 3) == "   3"
12922 // show_fill_left<int>('0', 4, 3) == "0003"
12923 // show_fill_left<int>(' ', 4, 12345) == "12345"
12924 template <typename T>
show_fill_left(const std::string::value_type & filler,std::size_t min_size,const T & x)12925 std::string show_fill_left(
12926     const std::string::value_type& filler, std::size_t min_size, const T& x)
12927 {
12928     return fill_left(filler, min_size, show<T>(x));
12929 }
12930 
12931 // API search type: show_fill_right : (Char, Int, a) -> String
12932 // fwd bind count: 2
12933 // Convert some value to a string with left-padded with some character.
12934 // (Int to String etc.)
12935 // Examples:
12936 // show_fill_right<int>(' ', 4, 3) == "3   "
12937 // show_fill_right<int>(' ', 4, 12345) == "12345"
12938 template <typename T>
show_fill_right(const std::string::value_type & filler,std::size_t min_size,const T & x)12939 std::string show_fill_right(const std::string::value_type& filler,
12940     std::size_t min_size, const T& x)
12941 {
12942     return fill_right(filler, min_size, show<T>(x));
12943 }
12944 
12945 } // namespace fplus
12946 
12947 //
12948 // string_tools.hpp
12949 //
12950 
12951 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
12952 // https://github.com/Dobiasd/FunctionalPlus
12953 // Distributed under the Boost Software License, Version 1.0.
12954 // (See accompanying file LICENSE_1_0.txt or copy at
12955 //  http://www.boost.org/LICENSE_1_0.txt)
12956 
12957 
12958 
12959 #include <cctype>
12960 #include <string>
12961 #include <locale>
12962 
12963 namespace fplus
12964 {
12965 
12966 // API search type: is_letter_or_digit : Char -> Bool
12967 // fwd bind count: 0
12968 // Is character alphanumerical?
12969 template <typename String>
is_letter_or_digit(const typename String::value_type & c)12970 bool is_letter_or_digit(const typename String::value_type& c)
12971 {
12972     return
12973         std::isdigit(static_cast<unsigned char>(c)) ||
12974         std::isalpha(static_cast<unsigned char>(c));
12975 }
12976 
12977 // API search type: is_whitespace : Char -> Bool
12978 // fwd bind count: 0
12979 // Is character a whitespace.
12980 template <typename String>
is_whitespace(const typename String::value_type & c)12981 bool is_whitespace(const typename String::value_type& c)
12982 {
12983     return (c == 32 || is_in_interval(9, 14, static_cast<int>(c)));
12984 }
12985 
12986 // API search type: is_line_break : Char -> Bool
12987 // fwd bind count: 0
12988 // Newline character ('\n')?
12989 template <typename String>
is_line_break(const typename String::value_type & c)12990 bool is_line_break(const typename String::value_type& c)
12991 {
12992     return c == '\n';
12993 }
12994 
12995 // API search type: clean_newlines : String -> String
12996 // fwd bind count: 0
12997 // Replaces windows and mac newlines with linux newlines.
12998 template <typename String>
clean_newlines(const String & str)12999 String clean_newlines(const String& str)
13000 {
13001     return replace_elems('\r', '\n',
13002         replace_tokens(String("\r\n"), String("\n"), str));
13003 }
13004 
13005 // API search type: split_words : (Bool, String) -> [String]
13006 // fwd bind count: 1
13007 // Splits a string by non-letter and non-digit characters.
13008 // split_words(false, "How are you?") == ["How", "are", "you"]
13009 template <typename String, typename ContainerOut = std::vector<String>>
split_words(const bool allowEmpty,const String & str)13010 ContainerOut split_words(const bool allowEmpty, const String& str)
13011 {
13012     return split_by(logical_not(is_letter_or_digit<String>), allowEmpty, str);
13013 }
13014 
13015 // API search type: split_lines : (Bool, String) -> [String]
13016 // fwd bind count: 1
13017 // Splits a string by the found newlines.
13018 // split_lines(false, "Hi,\nhow are you?") == ["Hi,", "How are you"]
13019 template <typename String, typename ContainerOut = std::vector<String>>
split_lines(bool allowEmpty,const String & str)13020 ContainerOut split_lines(bool allowEmpty, const String& str)
13021 {
13022     return split_by(is_line_break<String>, allowEmpty, clean_newlines(str));
13023 }
13024 
13025 // API search type: trim_whitespace_left : String -> String
13026 // fwd bind count: 0
13027 // trim_whitespace_left("    text  ") == "text  "
13028 template <typename String>
trim_whitespace_left(const String & str)13029 String trim_whitespace_left(const String& str)
13030 {
13031     return drop_while(is_whitespace<String>, str);
13032 }
13033 
13034 // API search type: trim_whitespace_right : String -> String
13035 // fwd bind count: 0
13036 // Remove whitespace characters from the end of a string.
13037 // trim_whitespace_right("    text  ") == "    text"
13038 template <typename String>
trim_whitespace_right(const String & str)13039 String trim_whitespace_right(const String& str)
13040 {
13041     return trim_right_by(is_whitespace<String>, str);
13042 }
13043 
13044 // API search type: trim_whitespace : String -> String
13045 // fwd bind count: 0
13046 // Remove whitespace characters from the beginning and the end of a string.
13047 // trim_whitespace("    text  ") == "text"
13048 template <typename String>
trim_whitespace(const String & str)13049 String trim_whitespace(const String& str)
13050 {
13051     return trim_by(is_whitespace<String>, str);
13052 }
13053 
13054 // API search type: to_lower_case : String -> String
13055 // fwd bind count: 0
13056 // Convert a string to lowercase characters.
13057 // to_lower_case("ChaRacTer&WorDs23") == "character&words23"
13058 template <typename String>
to_lower_case(const String & str)13059 String to_lower_case(const String& str)
13060 {
13061     typedef typename String::value_type Char;
13062     return transform([](Char c) -> Char
13063         {
13064             return static_cast<Char>(
13065                 std::tolower(static_cast<unsigned char>(c)));
13066         }, str);
13067 }
13068 
13069 // API search type: to_lower_case_loc : (Locale, String) -> String
13070 // fwd bind count: 1
13071 // Convert a string to lowercase characters using specified locale.
13072 // to_upper_case_loc(locale("ru_RU.utf8"), "cYrIlLiC КиРиЛлИцА") == "cyrillic кириллица"
13073 template <typename String>
to_lower_case_loc(const std::locale & lcl,const String & str)13074 String to_lower_case_loc(const std::locale &lcl, const String &str)
13075 {
13076   typedef typename String::value_type Char;
13077   return transform([&lcl](Char c) -> Char
13078       {
13079         return static_cast<Char>(
13080             std::tolower(c, lcl));
13081       }, str);
13082 }
13083 
13084 // API search type: to_upper_case : String -> String
13085 // fwd bind count: 0
13086 // Convert a string to uppercase characters.
13087 // to_upper_case("ChaRacTer&WorDs34") == "CHARACTER&WORDS34"
13088 template <typename String>
to_upper_case(const String & str)13089 String to_upper_case(const String& str)
13090 {
13091     typedef typename String::value_type Char;
13092     return transform([](Char c) -> Char
13093         {
13094             return static_cast<Char>(
13095                 std::toupper(static_cast<unsigned char>(c)));
13096         }, str);
13097 }
13098 
13099 // API search type: to_upper_case_loc : (Locale, String) -> String
13100 // fwd bind count: 1
13101 // Convert a string to uppercase characters using specified locale.
13102 // to_upper_case_loc(locale("ru_RU.utf8"), "cYrIlLiC КиРиЛлИцА") == "CYRILLIC КИРИЛЛИЦА"
13103 template <typename String>
to_upper_case_loc(const std::locale & lcl,const String & str)13104 String to_upper_case_loc(const std::locale &lcl, const String &str)
13105 {
13106   typedef typename String::value_type Char;
13107   return transform([&lcl](Char c) -> Char
13108       {
13109         return static_cast<Char>(
13110             std::toupper(c, lcl));
13111       }, str);
13112 }
13113 
13114 // API search type: to_string_fill_left : (Char, Int, a) -> String
13115 // fwd bind count: 2
13116 // Convert a type right-aligned string using a fill character.
13117 // to_string_fill_left('0', 5, 42) == "00042"
13118 // to_string_fill_left(' ', 5, 42) == "   42"
13119 template <typename T>
to_string_fill_left(const std::string::value_type & filler,std::size_t min_size,const T & x)13120 std::string to_string_fill_left(const std::string::value_type& filler,
13121         std::size_t min_size, const T& x)
13122 {
13123     return fill_left(filler, min_size, std::to_string(x));
13124 }
13125 
13126 // API search type: to_string_fill_right : (Char, Int, a) -> String
13127 // fwd bind count: 2
13128 // Convert a type left-aligned string using a fill character.
13129 // to_string_fill_right(' ', 5, 42) == "42   "
13130 template <typename T>
to_string_fill_right(const std::string::value_type & filler,std::size_t min_size,const T & x)13131 std::string to_string_fill_right(const std::string::value_type& filler,
13132         std::size_t min_size, const T& x)
13133 {
13134     return fill_right(filler, min_size, std::to_string(x));
13135 }
13136 
13137 } // namespace fplus
13138 
13139 //
13140 // tree.hpp
13141 //
13142 
13143 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
13144 // https://github.com/Dobiasd/FunctionalPlus
13145 // Distributed under the Boost Software License, Version 1.0.
13146 // (See accompanying file LICENSE_1_0.txt or copy at
13147 //  http://www.boost.org/LICENSE_1_0.txt)
13148 
13149 
13150 
13151 #include <vector>
13152 #include <queue>
13153 
13154 namespace fplus
13155 {
13156 
13157 template <typename T>
13158 struct tree
13159 {
treefplus::tree13160     tree (const T& value, const std::vector<tree<T>>& children) :
13161         value_(value), children_(children) {}
13162     T value_;
13163     std::vector<tree<T>> children_;
13164 };
13165 
13166 namespace internal
13167 {
13168 template <typename T>
make_singleton_tree(const T & x)13169 tree<T> make_singleton_tree(const T& x)
13170 {
13171     return {x, {}};
13172 }
13173 } // namespace internal
13174 
13175 namespace internal
13176 {
13177 
13178 template <typename BinaryPredicate, typename T>
presort_trees(BinaryPredicate tree_is_child_of,std::vector<tree<T>> xs_orig)13179 std::vector<tree<T>> presort_trees(BinaryPredicate tree_is_child_of,
13180     std::vector<tree<T>> xs_orig)
13181 {
13182     auto xs = fplus::convert_container<std::list<tree<T>>>(xs_orig);
13183     std::vector<tree<T>> result;
13184     while (!xs.empty())
13185     {
13186         for (auto it = std::begin(xs); it != std::end(xs);)
13187         {
13188             bool has_children = false;
13189             for (auto it_rest = std::begin(xs); it_rest != std::end(xs); ++it_rest)
13190             {
13191                 if (it_rest != it && tree_is_child_of(*it_rest, *it))
13192                 {
13193                     has_children = true;
13194                 }
13195             }
13196             if (!has_children)
13197             {
13198                 result.push_back(*it);
13199                 it = xs.erase(it);
13200             }
13201             else
13202             {
13203                 ++it;
13204             }
13205         }
13206     }
13207     return result;
13208 }
13209 
13210 template <typename BinaryPredicate, typename TreeCont> // todo: name?
trees_from_sequence_helper(BinaryPredicate tree_is_child_of,TreeCont xs_unsorted)13211 TreeCont trees_from_sequence_helper(
13212     BinaryPredicate tree_is_child_of, TreeCont xs_unsorted)
13213 {
13214     TreeCont result;
13215     auto xs = presort_trees(tree_is_child_of, xs_unsorted);
13216     for (auto it = std::begin(xs); it != std::end(xs); ++it)
13217     {
13218         const auto find_pred = bind_1st_of_2(tree_is_child_of, *it);
13219         auto it_find_begin = it;
13220         internal::advance_iterator(it_find_begin, 1);
13221         auto parent_it = std::find_if(it_find_begin, std::end(xs), find_pred);
13222         if (parent_it != std::end(xs))
13223         {
13224             parent_it->children_.push_back(*it);
13225         }
13226         else
13227         {
13228             result.push_back(*it);
13229         }
13230     }
13231     return result;
13232 }
13233 
13234 } // namespace internal
13235 
13236 // API search type: trees_from_sequence : (((a, a) -> Bool), [a]) -> [Tree a]
13237 // fwd bind count: 1
13238 // Converts the sequence into a tree considering the given binary predicate.
13239 template <typename BinaryPredicate, typename Container> // todo: name?
trees_from_sequence(BinaryPredicate is_child_of,const Container & xs)13240 std::vector<tree<typename Container::value_type>> trees_from_sequence(
13241     BinaryPredicate is_child_of, const Container& xs)
13242 {
13243     internal::check_binary_predicate_for_container<BinaryPredicate, Container>();
13244     typedef typename Container::value_type T;
13245     typedef tree<T> Tree;
13246     const auto singletons = transform_convert<std::vector<Tree>>(
13247         internal::make_singleton_tree<T>, xs);
13248     const auto tree_is_child_of =
13249         [is_child_of](const tree<T>& a, const tree<T>& b) -> bool
13250     {
13251         return is_child_of(a.value_, b.value_);
13252     };
13253     return internal::trees_from_sequence_helper(
13254         tree_is_child_of, std::move(singletons));
13255 }
13256 
13257 namespace internal
13258 {
13259 
13260 // -1 = a < b
13261 //  0 = a == b
13262 //  1 = b < a
13263 template <typename T>
tree_cmp(const tree<T> & a,const tree<T> & b)13264 int tree_cmp(const tree<T>& a, const tree<T>& b)
13265 {
13266     if(a.value_ < b.value_)
13267     {
13268         return -1;
13269     }
13270     else if(b.value_ < a.value_)
13271     {
13272         return 1;
13273     }
13274     else
13275     {
13276         const auto results = zip_with(tree_cmp<T>,
13277             sort_by(tree_cmp<T>, a.children_),
13278             sort_by(tree_cmp<T>, b.children_));
13279         return just_with_default(0, find_first_by(
13280                 bind_1st_of_2(is_not_equal<int>, 0),
13281                 results));
13282     }
13283 }
13284 
13285 template <typename T>
tree_less(const tree<T> & a,const tree<T> & b)13286 bool tree_less(const tree<T>& a, const tree<T>& b)
13287 {
13288     return tree_cmp(a, b) < 0;
13289 }
13290 
13291 } // namespace internal
13292 
13293 namespace internal
13294 {
13295 
13296 template <typename T>
are_normalized_trees_equal(const tree<T> & a,const tree<T> & b)13297 bool are_normalized_trees_equal(const tree<T>& a, const tree<T>& b)
13298 {
13299     if (a.value_ != b.value_ || a.children_.size() != b.children_.size())
13300     {
13301         return false;
13302     }
13303     else
13304     {
13305         return all(zip_with(are_normalized_trees_equal<T>,
13306             a.children_, b.children_));
13307     }
13308 }
13309 
13310 template <typename T>
normalize_tree(tree<T> x)13311 tree<T> normalize_tree(tree<T> x)
13312 {
13313     x.children_ = sort_by(
13314         internal::tree_less<T>,
13315         transform(normalize_tree<T>, x.children_));
13316     return x;
13317 }
13318 
13319 } // namespace internal
13320 
13321 // API search type: are_trees_equal : (Tree a, Tree a) -> Bool
13322 // fwd bind count: 1
13323 template <typename T>
are_trees_equal(const tree<T> & a,const tree<T> & b)13324 bool are_trees_equal(const tree<T>& a, const tree<T>& b)
13325 {
13326     return internal::are_normalized_trees_equal(
13327         internal::normalize_tree(a), internal::normalize_tree(b));
13328 }
13329 
13330 // API search type: tree_size : Tree a -> Int
13331 // fwd bind count: 0
13332 // A tree with only one element (root) has size 1.
13333 template <typename T>
tree_size(const tree<T> & x)13334 std::size_t tree_size(const tree<T>& x)
13335 {
13336     return 1 + sum(transform(tree_size<T>, x.children_));
13337 }
13338 
13339 // API search type: tree_depth : Tree a -> Int
13340 // fwd bind count: 0
13341 // A tree with only one element (root) has depth 1.
13342 template <typename T>
tree_depth(const tree<T> & x)13343 std::size_t tree_depth(const tree<T>& x)
13344 {
13345     return 1 + just_with_default<std::size_t>(0,
13346         maximum_maybe(transform(tree_depth<T>, x.children_)));
13347 }
13348 
13349 // API search type: flatten_tree_depth_first : Tree a -> [a]
13350 // fwd bind count: 0
13351 template <typename T>
flatten_tree_depth_first(const tree<T> & x)13352 std::vector<T> flatten_tree_depth_first(const tree<T>& x)
13353 {
13354     return prepend_elem(x.value_,
13355         transform_and_concat(flatten_tree_depth_first<T>, x.children_));
13356 }
13357 
13358 // API search type: flatten_tree_breadth_first : Tree a -> [a]
13359 // fwd bind count: 0
13360 template <typename T>
flatten_tree_breadth_first(const tree<T> & x)13361 std::vector<T> flatten_tree_breadth_first(const tree<T>& x)
13362 {
13363     std::vector<T> result;
13364     result.reserve(tree_size(x));
13365     std::queue<const tree<T>*> q;
13366     q.push(&x);
13367     while (!q.empty())
13368     {
13369         const auto current = q.front();
13370         q.pop();
13371         result.push_back(current->value_);
13372         for (const auto& c : current->children_)
13373         {
13374             q.push(&c);
13375         }
13376     }
13377     return result;
13378 }
13379 
13380 } // namespace fplus
13381 
13382 //
13383 // side_effects.hpp
13384 //
13385 
13386 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
13387 // https://github.com/Dobiasd/FunctionalPlus
13388 // Distributed under the Boost Software License, Version 1.0.
13389 // (See accompanying file LICENSE_1_0.txt or copy at
13390 //  http://www.boost.org/LICENSE_1_0.txt)
13391 
13392 
13393 
13394 #include <atomic>
13395 #include <chrono>
13396 #include <condition_variable>
13397 #include <cstdint>
13398 #include <fstream>
13399 #include <functional>
13400 #include <future>
13401 #include <iostream>
13402 #include <iterator>
13403 #include <streambuf>
13404 #include <string>
13405 #include <thread>
13406 #include <vector>
13407 
13408 namespace fplus
13409 {
13410 
13411 // Executes a function f in a fixed interval,
13412 // i.e. an average timespan between two consecutive calls of f,
13413 // given in microseconds.
13414 // f is a unary function, taking the time delta (in microseconds)
13415 // between the last and the current call as its argument.
13416 // In case of a delay outdated calls are be executed immediately.
13417 // So the average executation time of f should be way shorter
13418 // than the requested interval.
13419 // Call ticker::start() to run.
13420 // The ticker stops when ticker::stop() is called
13421 // or the instance runs out of scope.
13422 //
13423 // Example usage:
13424 //
13425 // void say_hi(std::int64_t)
13426 // {
13427 //     std::cout << "hi " << std::endl;
13428 // }
13429 // int main()
13430 // {
13431 //     ticker hi_ticker(say_hi, 2 * 1000 * 1000);
13432 //     hi_ticker.start();
13433 //     std::this_thread::sleep_for(std::chrono::milliseconds(4500));
13434 // }
13435 class ticker
13436 {
13437 public:
13438     typedef std::function<void(std::int64_t)> function;
ticker(const function & f,std::int64_t interval_us)13439     ticker(const function& f, std::int64_t interval_us) :
13440         f_(f),
13441         interval_us_(interval_us),
13442         control_mutex_(),
13443         is_running_(false),
13444         thread_(),
13445         stop_mutex_()
13446     {
13447     }
is_running()13448     bool is_running()
13449     {
13450         std::lock_guard<std::mutex> lock(control_mutex_);
13451         return is_running_;
13452     }
start()13453     bool start()
13454     {
13455         std::lock_guard<std::mutex> lock(control_mutex_);
13456         if (is_running_)
13457             return false;
13458         stop_mutex_.lock();
13459         thread_ = std::thread([this]() { thread_function(); });
13460         is_running_ = true;
13461         return true;
13462     }
stop()13463     bool stop()
13464     {
13465         std::lock_guard<std::mutex> lock(control_mutex_);
13466         if (!is_running_)
13467             return false;
13468         stop_mutex_.unlock();
13469         if (thread_.joinable())
13470         {
13471             thread_.join();
13472             thread_ = std::thread();
13473         }
13474         is_running_ = false;
13475         return true;
13476     }
~ticker()13477     ~ticker()
13478     {
13479         stop();
13480     }
13481 private:
thread_function()13482     void thread_function()
13483     {
13484         auto last_wake_up_time = std::chrono::steady_clock::now();
13485         auto last_time = last_wake_up_time;
13486         bool quit = false;
13487         while (!quit)
13488         {
13489             const auto wake_up_time =
13490                 last_wake_up_time + std::chrono::microseconds{ interval_us_ };
13491             const auto sleep_time =
13492                 wake_up_time - std::chrono::steady_clock::now();
13493             if (stop_mutex_.try_lock_for(sleep_time))
13494             {
13495                 stop_mutex_.unlock();
13496                 quit = true;
13497             }
13498             const auto current_time = std::chrono::steady_clock::now();
13499             const auto elapsed = current_time - last_time;
13500             last_wake_up_time = wake_up_time;
13501             last_time = current_time;
13502             const auto elapsed_us =
13503                 std::chrono::duration_cast<std::chrono::microseconds>(
13504                     elapsed).count();
13505             try
13506             {
13507                 f_(elapsed_us);
13508             }
13509             catch (...)
13510             {
13511             }
13512         }
13513     }
13514     const function f_;
13515     const std::int64_t interval_us_;
13516     std::mutex control_mutex_;
13517     bool is_running_;
13518     std::thread thread_;
13519     std::timed_mutex stop_mutex_;
13520 };
13521 
13522 
13523 // API search type: sleep_for_n_seconds : Int -> Io ()
13524 // Returns a function that suspends
13525 // the calling thread for n seconds when executed.
13526 inline
sleep_for_n_seconds(std::size_t seconds)13527 std::function<void()> sleep_for_n_seconds(std::size_t seconds)
13528 {
13529     return [seconds]()
13530     {
13531         std::this_thread::sleep_for(std::chrono::seconds(seconds));
13532     };
13533 }
13534 
13535 // API search type: sleep_for_n_milliseconds : Int -> Io ()
13536 // Returns a function that suspends
13537 // the calling thread for n milliseconds when executed.
13538 inline
sleep_for_n_milliseconds(std::size_t milliseconds)13539 std::function<void()> sleep_for_n_milliseconds(std::size_t milliseconds)
13540 {
13541     return [milliseconds]()
13542     {
13543         std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
13544     };
13545 }
13546 
13547 // API search type: sleep_for_n_microseconds : Int -> Io ()
13548 // Returns a function that suspends
13549 // the calling thread for n microseconds when executed.
13550 inline
sleep_for_n_microseconds(std::size_t microseconds)13551 std::function<void()> sleep_for_n_microseconds(std::size_t microseconds)
13552 {
13553     return [microseconds]()
13554     {
13555         std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
13556     };
13557 }
13558 
13559 // API search type: execute_serially : [Io ()] -> Io ()
13560 // Returns a function that executes
13561 // the given side effects one after another when called.
13562 template <typename Container>
execute_serially(const Container & effs)13563 auto execute_serially(const Container& effs)
13564 {
13565     using Effect = typename Container::value_type;
13566     using Result = internal::invoke_result_t<Effect>;
13567 
13568     return [effs]
13569     {
13570         std::vector<std::decay_t<Result>> results;
13571         for (const Effect& e : effs)
13572         {
13573             results.push_back(internal::invoke(e));
13574         }
13575         return results;
13576     };
13577 }
13578 
13579 // API search type: execute_serially_until_success : [Io Bool] -> Io Bool
13580 // Returns a function that (when called) executes
13581 // the given side effects one after another until one of it returns true.
13582 template <typename Container>
execute_serially_until_success(const Container & effs)13583 auto execute_serially_until_success(const Container& effs)
13584 {
13585     using Effect = typename Container::value_type;
13586     using Result = internal::invoke_result_t<Effect>;
13587     static_assert(std::is_convertible<Result, bool>::value,
13588                   "Effects must return a boolish type.");
13589     return [effs]() -> bool
13590     {
13591         for (const Effect& e : effs)
13592         {
13593             if (internal::invoke(e))
13594             {
13595                 return true;
13596             }
13597         }
13598         return false;
13599     };
13600 }
13601 
13602 // API search type: execute_and_return_fixed_value : (a, [Io b]) -> Io a
13603 // Returns a function that executes the given side effect
13604 // and returns a fixed value when called.
13605 template <typename Result, typename Effect>
execute_and_return_fixed_value(Result result,Effect eff)13606 std::function<Result()> execute_and_return_fixed_value(
13607         Result result,
13608         Effect eff)
13609 {
13610     return [eff, result]() -> Result
13611     {
13612         eff();
13613         return result;
13614     };
13615 }
13616 
13617 // Converts an arbitrary callable effect to an std::function.
13618 template <typename Effect>
effect_to_std_function(Effect eff)13619 std::function<internal::invoke_result_t<Effect> ()> effect_to_std_function(Effect eff)
13620 {
13621     return [eff]
13622     {
13623         return internal::invoke(eff);
13624     };
13625 }
13626 
13627 // API search type: execute_max_n_times_until_success : (Int, Io (), Int) -> Io Bool
13628 // Returns a function that (when called) executes a side effect
13629 // until it succeds once or the maximum number
13630 // of attempts with an optional pause in between.
13631 template <typename Effect>
execute_max_n_times_until_success(std::size_t n,const Effect & eff,std::size_t pause_in_milliseconds=0)13632 auto execute_max_n_times_until_success(std::size_t n,
13633                                        const Effect& eff,
13634                                        std::size_t pause_in_milliseconds = 0)
13635 {
13636     if (pause_in_milliseconds > 0)
13637     {
13638         auto sleep_and_return_false =
13639             execute_and_return_fixed_value(
13640                 false,
13641                 sleep_for_n_milliseconds(pause_in_milliseconds));
13642         return execute_serially_until_success(
13643             intersperse(
13644                 sleep_and_return_false,
13645                 replicate(n, effect_to_std_function(eff))));
13646     }
13647     return execute_serially_until_success(
13648         replicate(n, effect_to_std_function(eff)));
13649 }
13650 
13651 // API search type: execute_n_times : (Int, Io a) -> Io ()
13652 // Returns a function that (when called) executes n times
13653 // the provided side effect function.
13654 // The return values (if present) are dropped.
13655 template<typename Effect>
execute_n_times(std::size_t n,const Effect & eff)13656 auto execute_n_times(std::size_t n, const Effect& eff)
13657 {
13658     for (auto _ : fplus::numbers(static_cast<size_t>(0), n))
13659     {
13660         (void) _; // suppress warning / unused variable
13661         eff();
13662     }
13663 }
13664 
13665 // API search type: execute_serially_until_failure : [Io Bool] -> Io Bool
13666 // Returns a function that (when called) executes the given side effects
13667 // one after another until one of them returns false.
13668 template <typename Container>
execute_serially_until_failure(const Container & effs)13669 std::function<bool()> execute_serially_until_failure(const Container& effs)
13670 {
13671     using Effect = typename Container::value_type;
13672     using Result = internal::invoke_result_t<Effect>;
13673     static_assert(std::is_convertible<Result, bool>::value,
13674         "Effects must return a boolish type.");
13675     return [effs]() -> bool
13676     {
13677         for (const Effect& e : effs)
13678         {
13679             if (!internal::invoke(e))
13680             {
13681                 return false;
13682             }
13683         }
13684         return true;
13685     };
13686 }
13687 
13688 // API search type: execute_parallelly : [Io a] -> Io [a]
13689 // Returns a function that (when called) executes the given side effects
13690 // in parallel (one thread each) and returns the collected results.
13691 template <typename Container>
execute_parallelly(const Container & effs)13692 auto execute_parallelly(const Container& effs)
13693 {
13694     return [effs] {
13695         // Bluntly re-using the transform implementation to execute side effects.
13696         return transform_parallelly([](const auto& eff) {
13697             return internal::invoke(eff);
13698         }, effs);
13699     };
13700 }
13701 
13702 // API search type: execute_parallelly_n_threads : (Int, [Io a]) -> Io [a]
13703 // Returns a function that (when called) executes the given side effects
13704 // in parallel (one thread each) and returns the collected results.
13705 template <typename Container>
execute_parallelly_n_threads(std::size_t n,const Container & effs)13706 auto execute_parallelly_n_threads(std::size_t n, const Container& effs)
13707 {
13708     return [n, effs] {
13709         // Bluntly re-using the transform implementation to execute side effects.
13710         return transform_parallelly_n_threads(n, [](const auto& eff) {
13711             return internal::invoke(eff);
13712         }, effs);
13713     };
13714 }
13715 
13716 // API search type: execute_fire_and_forget : Io a -> Io a
13717 // Returns a function that (when called) executes the given side effect
13718 // in a new thread and returns immediately.
13719 template <typename Effect>
execute_fire_and_forget(Effect eff)13720 std::function<void()> execute_fire_and_forget(Effect eff)
13721 {
13722     return [eff]()
13723     {
13724         std::thread t(eff);
13725         t.detach();
13726     };
13727 }
13728 
13729 // API search type: read_text_file_maybe : String -> Io (Maybe String)
13730 // Returns a function that reads the content of a text file when called.
13731 inline
read_text_file_maybe(const std::string & filename)13732 std::function<maybe<std::string>()> read_text_file_maybe(
13733     const std::string& filename)
13734 {
13735     return [filename]() -> maybe<std::string>
13736     {
13737         std::ifstream input(filename);
13738         if (!input.good())
13739             return {};
13740         return just(std::string(
13741                 std::istreambuf_iterator<std::string::value_type>(input),
13742                 std::istreambuf_iterator<std::string::value_type>()));
13743     };
13744 }
13745 
13746 // API search type: read_text_file : String -> Io String
13747 // Returns a function that reads the content of a text file when called.
13748 // This function then returns an empty string if the file could not be read.
13749 inline
read_text_file(const std::string & filename)13750 std::function<std::string()> read_text_file(const std::string& filename)
13751 {
13752     return [filename]() -> std::string
13753     {
13754         return just_with_default(
13755             std::string(),
13756 
13757             read_text_file_maybe(filename)());
13758     };
13759 }
13760 
13761 // API search type: read_binary_file_maybe : String -> Io (Maybe [Int])
13762 // Returns a function that reads the content of a binary file when executed.
13763 inline
read_binary_file_maybe(const std::string & filename)13764 std::function<maybe<std::vector<std::uint8_t>>()> read_binary_file_maybe(
13765     const std::string& filename)
13766 {
13767     return [filename]() -> maybe<std::vector<std::uint8_t>>
13768     {
13769         std::ifstream file(filename, std::ios::binary);
13770         if (!file.good())
13771             return {};
13772         file.unsetf(std::ios::skipws);
13773         std::streampos fileSize;
13774         file.seekg(0, std::ios::end);
13775         fileSize = file.tellg();
13776         if (fileSize == static_cast<std::streamsize>(0))
13777             return {};
13778         file.seekg(0, std::ios::beg);
13779         std::vector<std::uint8_t> vec(static_cast<std::size_t>(fileSize), 0);
13780         file.read(reinterpret_cast<char*>(&vec[0]), fileSize);
13781         return vec;
13782     };
13783 }
13784 
13785 // API search type: read_binary_file : String -> Io [Int]
13786 // Returns a function that reads the content of a binary file when executed.
13787 // This function then returns an empty vector if the file could not be read.
13788 inline
read_binary_file(const std::string & filename)13789 std::function<std::vector<std::uint8_t>()> read_binary_file(
13790     const std::string& filename)
13791 {
13792     return [filename]() -> std::vector<std::uint8_t>
13793     {
13794         return just_with_default(
13795             std::vector<std::uint8_t>(),
13796             read_binary_file_maybe(filename)());
13797     };
13798 }
13799 
13800 // API search type: read_text_file_lines_maybe : (String, Bool) -> Io (Maybe [String])
13801 // Returns a function that (when called) reads the content of a text file
13802 // and returns it line by line.
13803 inline
read_text_file_lines_maybe(bool allow_empty,const std::string & filename)13804 std::function<maybe<std::vector<std::string>>()> read_text_file_lines_maybe(
13805         bool allow_empty, const std::string& filename)
13806 {
13807     return [filename, allow_empty]() -> maybe<std::vector<std::string>>
13808     {
13809         const auto maybe_content = read_text_file_maybe(filename)();
13810         if (maybe_content.is_nothing())
13811             return {};
13812         else
13813             return split_lines(allow_empty, maybe_content.unsafe_get_just());
13814     };
13815 }
13816 
13817 // API search type: read_text_file_lines : (String, Bool) -> Io [String]
13818 // Returns a function that (when called) reads the content of a text file
13819 // and returns it line by line.
13820 // This function then returns an empty vector if the file could not be read.
13821 inline
read_text_file_lines(bool allow_empty,const std::string & filename)13822 std::function<std::vector<std::string>()> read_text_file_lines(
13823         bool allow_empty, const std::string& filename)
13824 {
13825     return [filename, allow_empty]() -> std::vector<std::string>
13826     {
13827         return just_with_default(
13828             std::vector<std::string>(),
13829             read_text_file_lines_maybe(allow_empty, filename)());
13830     };
13831 }
13832 
13833 // API search type: write_text_file : (String, String) -> Io Bool
13834 // Returns a function that (when called) writes content into a text file,
13835 // replacing it if it already exists.
13836 inline
write_text_file(const std::string & filename,const std::string & content)13837 std::function<bool()> write_text_file(const std::string& filename,
13838         const std::string& content)
13839 {
13840     return [filename, content]() -> bool
13841     {
13842         std::ofstream output(filename);
13843         output << content;
13844         return output.good();
13845     };
13846 }
13847 
13848 // API search type: write_binary_file : (String, [Int]) -> Io Bool
13849 // Returns a function that (when called) writes content into a binary file,
13850 // replacing it if it already exists.
13851 inline
write_binary_file(const std::string & filename,const std::vector<uint8_t> & content)13852 std::function<bool()> write_binary_file(const std::string& filename,
13853         const std::vector<uint8_t>& content)
13854 {
13855     return [filename, content]() -> bool
13856     {
13857         std::ofstream file(filename, std::ios::binary);
13858         file.write(reinterpret_cast<const char*>(&content[0]),
13859             static_cast<std::streamsize>(content.size()));
13860         return file.good();
13861     };
13862 }
13863 
13864 // API search type: write_text_file_lines : (String, [String], Bool) -> Io Bool
13865 // Returns a function that (when called) writes lines into a text file,
13866 // replacing it if it already exists.
13867 inline
write_text_file_lines(bool trailing_newline,const std::string & filename,const std::vector<std::string> & lines)13868 std::function<bool()> write_text_file_lines(bool trailing_newline,
13869         const std::string& filename,
13870         const std::vector<std::string>& lines)
13871 {
13872     std::string content = join(std::string("\n"), lines);
13873     if (trailing_newline)
13874     {
13875         content += "\n";
13876     }
13877     return write_text_file(filename, content);
13878 }
13879 
13880 // API search type: execute_effect : Io a -> a
13881 // Simply run a side effect (call a function without parameters)
13882 // and returns the result.
13883 // Can be useful for chaining.
13884 template <typename F>
execute_effect(const F f)13885 auto execute_effect(const F f)
13886 {
13887     return internal::invoke(f);
13888 }
13889 
13890 // API search type: interact : (String -> String) -> Io ()
13891 // Takes a function F of type (String -> String)
13892 // and returns a function that
13893 // reads the entire input from standard input,
13894 // passes it through the given function,
13895 // and writes the result to standard output.
13896 template <typename F>
interact(F f)13897 std::function<void()> interact(F f)
13898 {
13899     return [f]() -> void
13900     {
13901         std::cout << f(std::string(
13902             std::istreambuf_iterator<char>(std::cin.rdbuf()),
13903             std::istreambuf_iterator<char>()));
13904     };
13905 }
13906 
13907 // API search type: execute_with_maybe : ((a -> void), Maybe a) -> Io Bool
13908 // Returns a function that
13909 // akes a unary side-effect function with
13910 // a maybe holding a matching type
13911 // and runs the sideeffect if the Maybe holds a just.
13912 // The returned function returns false if the maybe was a nothing.
13913 template <typename Effect, typename X>
execute_with_maybe(Effect eff,const maybe<X> & m)13914 std::function<bool()> execute_with_maybe(Effect eff, const maybe<X>& m)
13915 {
13916     return [eff, m]() -> bool
13917     {
13918         if (m.is_nothing())
13919         {
13920             return false;
13921         }
13922         eff(m.unsafe_get_just());
13923         return true;
13924     };
13925 }
13926 
13927 } // namespace fplus
13928 
13929 //
13930 // stopwatch.hpp
13931 //
13932 
13933 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
13934 // https://github.com/Dobiasd/FunctionalPlus
13935 // Distributed under the Boost Software License, Version 1.0.
13936 // (See accompanying file LICENSE_1_0.txt or copy at
13937 //  http://www.boost.org/LICENSE_1_0.txt)
13938 
13939 
13940 #include <chrono>
13941 
13942 namespace fplus
13943 {
13944 
13945 class stopwatch
13946 {
13947 public:
stopwatch()13948     stopwatch() : beg_(clock::now()) {}
reset()13949     void reset() { beg_ = clock::now(); }
13950 
13951     // time since creation or last reset in seconds
elapsed() const13952     double elapsed() const {
13953         return std::chrono::duration_cast<second>
13954             (clock::now() - beg_).count(); }
13955 private:
13956     typedef std::chrono::high_resolution_clock clock;
13957     typedef std::chrono::duration<double, std::ratio<1>> second;
13958     std::chrono::time_point<clock> beg_;
13959 };
13960 
13961 } // namespace fplus
13962 
13963 //
13964 // variant.hpp
13965 //
13966 
13967 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
13968 // https://github.com/Dobiasd/FunctionalPlus
13969 // Distributed under the Boost Software License, Version 1.0.
13970 // (See accompanying file LICENSE_1_0.txt or copy at
13971 //  http://www.boost.org/LICENSE_1_0.txt)
13972 
13973 
13974 
13975 #include <iostream>
13976 #include <memory>
13977 #include <tuple>
13978 
13979 namespace fplus
13980 {
13981 
13982 namespace internal
13983 {
13984 
13985     // http://stackoverflow.com/a/18987405/1866775
13986 
13987     template <typename...>
13988     struct is_one_of;
13989 
13990     template <typename F>
13991     struct is_one_of<F>
13992     {
13993         static constexpr bool value = false;
13994     };
13995 
13996     template <typename F, typename S, typename... T>
13997     struct is_one_of<F, S, T...>
13998     {
13999         static constexpr bool value = std::is_same<F, S>::value
14000             || is_one_of<F, T...>::value;
14001     };
14002 
14003     template <typename F, typename... T>
14004     struct is_one_of<F, std::tuple<T...>>
14005     {
14006         static constexpr bool value = is_one_of<F, T...>::value;
14007     };
14008 
14009     template <typename...>
14010     struct is_unique;
14011 
14012     template <>
14013     struct is_unique<> {
14014         static constexpr bool value = true;
14015     };
14016 
14017     template<typename F, typename... T>
14018     struct is_unique<F, T...>
14019     {
14020         static constexpr bool value = is_unique<T...>::value
14021             && !is_one_of<F, T...>::value;
14022     };
14023 
14024     template<typename... T>
14025     struct is_unique<std::tuple<T...>>
14026     {
14027         static constexpr bool value = is_unique<T...>::value;
14028     };
14029 
14030     template <typename...>
14031     struct are_same;
14032 
14033     template <>
14034     struct are_same<> {
14035         static constexpr bool value = true;
14036     };
14037 
14038     template<typename F1, typename F2>
14039     struct are_same<F1, F2>
14040     {
14041         static constexpr bool value = std::is_same<F1, F2>::value;
14042     };
14043 
14044     template<typename F1, typename F2, typename... T>
14045     struct are_same<F1, F2, T...>
14046     {
14047         static constexpr bool value = are_same<F2, T...>::value
14048             && std::is_same<F1, F2>::value;
14049     };
14050 
14051     template<typename... T>
14052     struct are_same<std::tuple<T...>>
14053     {
14054         static constexpr bool value = are_same<T...>::value;
14055     };
14056 
14057     // http://stackoverflow.com/a/3273571/1866775
14058     template<template<typename...> class List,
14059         template<typename> class Mod,
14060         typename ...Args>
14061     struct transform_parameter_pack {
14062         typedef List<typename Mod<Args>::type...> type;
14063     };
14064 
14065     template<typename T>
14066     struct as_shared_pointer
14067     {
14068         typedef std::shared_ptr<T> type;
14069     };
14070 
14071 
14072 
14073     // http://stackoverflow.com/a/27588263/1866775
14074 
14075     template <typename T, typename... Ts> struct get_index;
14076 
14077     template <typename T, typename... Ts>
14078     struct get_index<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
14079 
14080     template <typename T, typename Tail, typename... Ts>
14081     struct get_index<T, Tail, Ts...> :
14082         std::integral_constant<std::size_t, 1 + get_index<T, Ts...>::value> {};
14083 
14084     template <typename T>
14085     struct get_index<T>
14086     {
14087         // condition is always false, but should be dependant of T
14088         static_assert(sizeof(T) == 0, "element not found");
14089     };
14090 
14091 
14092     template <typename T, typename ... Ts>
14093     struct parameter_pack_head
14094     {
14095         typedef T type;
14096     };
14097 
14098 
14099     template <typename F>
14100     struct function_first_input_type
14101     {
14102         typedef typename std::remove_const<
14103             typename std::remove_reference<
14104                 typename utils::function_traits<
14105                     F>::template arg<0>::type>::type>::type
14106             type;
14107     };
14108 
14109     template <typename F>
14110     struct unary_function_result_type
14111     {
14112         static_assert(utils::function_traits<F>::arity == 1,
14113                 "Wrong arity.");
14114         typedef typename function_first_input_type<F>::type T;
14115         typedef std::decay_t<internal::invoke_result_t<F, T>> type;
14116     };
14117 
14118 
14119     // http://stackoverflow.com/a/42493805/1866775
14120 
14121     template <typename T>
14122     struct tag { };
14123 
14124     template <typename... Ts>
14125     struct type_set_eq_helper: tag<Ts>... { };
14126 
14127     template <typename, typename, typename = void>
14128     struct type_set_eq: std::false_type { };
14129 
14130     template <bool...>
14131     struct bool_pack { };
14132 
14133     template <bool... Bs>
14134     using my_and = std::is_same<bool_pack<Bs..., true>, bool_pack<true, Bs...>>;
14135 
14136     template <typename... Ts1, typename... Ts2>
14137     struct type_set_eq<std::tuple<Ts1...>, std::tuple<Ts2...>, typename std::enable_if< (sizeof...(Ts1) == sizeof...(Ts2)) && my_and< std::is_base_of<tag<Ts2>, type_set_eq_helper<Ts1...>>::value...  >::value  >::type  >:
14138        std::true_type { };
14139 
14140 
14141     // http://stackoverflow.com/a/42581257/1866775
14142 
14143     template <typename Lhs, typename Rhs>
14144     struct is_superset_of;
14145 
14146     template <typename Tuple, typename T, typename... Ts>
14147     struct is_superset_of<Tuple, std::tuple<T, Ts...>>
14148     {
14149         static const bool value = is_one_of<T, Tuple>::value && is_superset_of<Tuple, std::tuple<Ts...>>::value;
14150     };
14151 
14152     template <typename Tuple>
14153     struct is_superset_of<Tuple, std::tuple<>>
14154     {
14155         static const bool value = true;
14156     };
14157 
14158 
14159     // http://stackoverflow.com/a/36934374/1866775
14160     template<bool... bs>
14161     using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;
14162 
14163 } // namespace internal
14164 
14165 
14166 template<typename ... Types>
14167 struct variant
14168 {
14169     static_assert(internal::is_unique<Types...>::value, "Types must be unique.");
14170     static_assert(internal::all_true<(!std::is_reference<Types>::value)...>::value, "No reference types allowed.");
14171     static_assert(internal::all_true<(!std::is_const<Types>::value)...>::value, "No const types allowed.");
14172     static_assert(sizeof...(Types) >= 1, "Please provide at least one type.");
14173 
14174     template <typename T>
variantfplus::variant14175     variant(const T& val) : shared_ptrs_({})
14176     {
14177         std::get<internal::get_index<T, Types...>::value>(shared_ptrs_) =
14178             std::make_shared<T>(val);
14179     }
14180 
14181     template <typename T>
isfplus::variant14182     bool is() const
14183     {
14184         static_assert(
14185             internal::is_one_of<T, Types...>::value
14186             , "Type must match one possible variant type.");
14187 
14188         const auto ptr =
14189             std::get<internal::get_index<T, Types...>::value>(shared_ptrs_);
14190 
14191         return static_cast<bool>(ptr);
14192     }
14193 
operator ==(const variant<Types...> & a,const variant<Types...> & b)14194     friend bool operator== (
14195         const variant<Types...>& a, const variant<Types...>& b)
14196     {
14197         return a.shared_ptrs_ == b.shared_ptrs_;
14198     }
14199 
operator !=(const variant<Types...> & a,const variant<Types...> & b)14200     friend bool operator!= (
14201         const variant<Types...>& a, const variant<Types...>& b)
14202     {
14203         return a.shared_ptrs_ != b.shared_ptrs_;
14204     }
14205 
14206     template <typename F>
visit_onefplus::variant14207     auto visit_one(F f) const
14208     {
14209         using T = typename internal::function_first_input_type<F>::type;
14210         using Ret = internal::invoke_result_t<F, T>;
14211         internal::trigger_static_asserts<internal::unary_function_tag, F, T>();
14212 
14213         static_assert(
14214             internal::is_one_of<
14215                 typename internal::function_first_input_type<F>::type,
14216                 Types...>::value
14217             , "Function input must match one variant type.");
14218 
14219         static_assert(!std::is_same<std::decay_t<Ret>, void>::value,
14220                       "Function must return non-void type.");
14221 
14222         const auto ptr =
14223             std::get<internal::get_index<T, Types...>::value>(shared_ptrs_);
14224 
14225         if (ptr)
14226         {
14227             return just(internal::invoke(f, *ptr));
14228         }
14229 
14230         return nothing<std::decay_t<Ret>>();
14231     }
14232 
14233     template <typename ...Fs>
visitfplus::variant14234     auto visit(Fs ... fs) const ->
14235         typename internal::unary_function_result_type<
14236             typename internal::parameter_pack_head<Fs...>::type>::type
14237     {
14238         typedef typename internal::unary_function_result_type<
14239             typename internal::parameter_pack_head<Fs...>::type>::type
14240             Res;
14241 
14242         static_assert(
14243             sizeof...(Fs) >= std::tuple_size<shared_ptr_pack>::value,
14244             "Too few functions provided.");
14245 
14246         static_assert(
14247             sizeof...(Fs) <= std::tuple_size<shared_ptr_pack>::value,
14248             "Too many functions provided.");
14249 
14250         typedef typename internal::transform_parameter_pack<
14251             std::tuple,
14252             internal::unary_function_result_type,
14253             Fs...
14254             >::type return_types_tuple;
14255 
14256         typedef typename internal::transform_parameter_pack<
14257             std::tuple,
14258             internal::function_first_input_type,
14259             Fs...
14260             >::type function_first_input_types_tuple;
14261 
14262         static_assert(
14263             internal::is_unique<function_first_input_types_tuple>::value,
14264             "Only one function per input type allowed.");
14265 
14266         static_assert(
14267             internal::are_same<return_types_tuple>::value,
14268             "All Functions must return the same type.");
14269 
14270         static_assert(
14271             internal::type_set_eq<function_first_input_types_tuple, std::tuple<Types...>>::value,
14272             "Functions do not cover all possible types.");
14273 
14274         const auto results = justs(visit_helper<Res>(fs...));
14275         assert(size_of_cont(results) == 1);
14276         return head(results);
14277     }
14278 
14279     template <typename ...Fs>
transformfplus::variant14280     variant<Types...> transform(Fs ... fs) const
14281     {
14282         static_assert(
14283             sizeof...(Fs) >= std::tuple_size<shared_ptr_pack>::value,
14284             "Too few functions provided.");
14285 
14286         static_assert(
14287             sizeof...(Fs) <= std::tuple_size<shared_ptr_pack>::value,
14288             "Too many functions provided.");
14289 
14290         typedef typename internal::transform_parameter_pack<
14291             std::tuple,
14292             internal::unary_function_result_type,
14293             Fs...
14294             >::type return_types_tuple;
14295 
14296         typedef typename internal::transform_parameter_pack<
14297             std::tuple,
14298             internal::function_first_input_type,
14299             Fs...
14300             >::type function_first_input_types_tuple;
14301 
14302         static_assert(
14303             internal::type_set_eq<function_first_input_types_tuple, std::tuple<Types...>>::value,
14304             "Functions do not cover all possible types.");
14305 
14306         static_assert(
14307             internal::is_superset_of<std::tuple<Types...>, return_types_tuple>::value,
14308             "All Functions must return a possible variant type.");
14309 
14310         return visit(fs...);
14311     }
14312 
14313 private:
14314     template <typename Res, typename F>
visit_helperfplus::variant14315     std::vector<fplus::maybe<Res>> visit_helper(F f) const
14316     {
14317         return {visit_one(f)};
14318     }
14319 
14320     template <typename Res, typename F, typename ...Fs>
visit_helperfplus::variant14321     std::vector<fplus::maybe<Res>> visit_helper(F f, Fs ... fs) const
14322     {
14323         return fplus::append(visit_helper<Res>(f), visit_helper<Res>(fs...));
14324     }
14325 
14326     typedef typename internal::transform_parameter_pack<
14327         std::tuple,
14328         internal::as_shared_pointer,
14329         Types...
14330     >::type shared_ptr_pack;
14331     shared_ptr_pack shared_ptrs_;
14332 };
14333 
14334 } // namespace fplus
14335 
14336 //
14337 // timed.hpp
14338 //
14339 
14340 
14341 #include <chrono>
14342 #include <type_traits>
14343 
14344 #include <cassert>
14345 #include <exception>
14346 #include <functional>
14347 #include <memory>
14348 
14349 namespace fplus
14350 {
14351 using ExecutionTime = double; // in seconds
14352 
14353 // Holds a value of type T plus an execution time
14354 template <typename T>
14355 class timed : public std::pair<T, ExecutionTime>
14356 {
14357     using base_pair = std::pair<T, ExecutionTime>;
14358 public:
timed()14359     timed() : base_pair() {}
timed(const T & val,ExecutionTime t=0.)14360     timed(const T& val, ExecutionTime t = 0.) : base_pair(val, t) {}
14361 
14362     // Execution time in seconds (returns a double)
time_in_s() const14363     ExecutionTime time_in_s() const { return base_pair::second; }
14364 
14365     // Execution time as a std::chrono::duration<double>
duration_in_s() const14366     std::chrono::duration<double, std::ratio<1>> duration_in_s() const
14367     {
14368         return std::chrono::duration<double, std::ratio<1>>(time_in_s());
14369     }
14370 
14371     // Inner value
get() const14372     const T& get() const            { return base_pair::first; }
get()14373     T& get()                        { return base_pair::first; }
14374 };
14375 
14376 // API search type: show_timed : Timed a -> String
14377 // fwd bind count: 0
14378 // show_timed((42,1)) -> "42 (1000ms)"
14379 template <typename T>
show_timed(const fplus::timed<T> & v)14380 std::string show_timed(const fplus::timed<T>& v)
14381 {
14382     std::string result =
14383         fplus::show(v.get()) + " (" + fplus::show(v.time_in_s() * 1000.) + "ms)";
14384     return result;
14385 }
14386 
14387 namespace internal
14388 {
14389     template<typename Fn>
14390     class timed_function_impl
14391     {
14392     public:
timed_function_impl(Fn fn)14393         explicit timed_function_impl(Fn fn) : _fn(fn) {};
operator ()(Args &&...args)14394         template<typename ...Args> auto operator()(Args&&... args)
14395         {
14396             return _timed_result(std::forward<Args>(args)...);
14397         }
14398 
14399     private:
14400         template<typename ...Args>
_timed_result(Args &&...args)14401         auto _timed_result(Args&&... args)
14402         {
14403             fplus::stopwatch timer;
14404             auto r = _fn(std::forward<Args>(args)...);
14405             auto r_t = fplus::timed<decltype(r)>(r, timer.elapsed());
14406             return r_t;
14407         }
14408 
14409         Fn _fn;
14410     };
14411 }
14412 
14413 // API search type: make_timed_function : ((a -> b)) -> (a -> Timed b)
14414 // fwd bind count: 0
14415 // Transforms a function into a timed / benchmarked version of the same function.
14416 // -
14417 // Example:
14418 // -
14419 // using Ints = std::vector<int>;
14420 // Ints ascending_numbers = fplus::numbers(0, 1000);
14421 // Ints shuffled_numbers = fplus::shuffle(std::mt19937::default_seed, ascending_numbers);
14422 // auto sort_func = [](const Ints& values) { return fplus::sort(values); };
14423 // auto sort_bench = fplus::make_timed_function(sort_func);
14424 // auto sorted_numbers = sort_bench(shuffled_numbers);
14425 // assert(sorted_numbers.get() == ascending_numbers); // sorted_numbers.get() <=> actual output
14426 // assert(sorted_numbers.time_in_s() < 0.1); // // sorted_numbers.time_in_s() <=> execution time
14427 template<class Fn>
make_timed_function(Fn f)14428 auto make_timed_function(Fn f)
14429 {
14430     return internal::timed_function_impl<decltype(f)>(f);
14431 }
14432 
14433 namespace internal
14434 {
14435     template<typename Fn>
14436     class timed_void_function_impl
14437     {
14438     public:
timed_void_function_impl(Fn fn)14439         explicit timed_void_function_impl(Fn fn) : _fn(fn) {};
operator ()(Args &&...args)14440         template<typename ...Args> auto operator()(Args&&... args)
14441         {
14442             return _timed_result(std::forward<Args>(args)...);
14443         }
14444 
14445     private:
14446         template<typename ...Args>
_timed_result(Args &&...args)14447         auto _timed_result(Args&&... args)
14448         {
14449             fplus::stopwatch timer;
14450             _fn(std::forward<Args>(args)...);
14451             return timer.elapsed();
14452         }
14453 
14454         Fn _fn;
14455     };
14456 
14457 }
14458 
14459 // API search type: make_timed_void_function : ((a -> Void)) -> (a -> Double)
14460 // fwd bind count: 0
14461 // Transforms a void function into a timed / benchmarked version of the same function.
14462 // -
14463 // Example:
14464 // -
14465 // void foo() { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); }
14466 // ...
14467 // auto foo_bench = make_timed_void_function(foo);
14468 // auto r = foo_bench();
14469 // double run_time = foo_bench(); // in seconds
14470 template<class Fn>
make_timed_void_function(Fn f)14471 auto make_timed_void_function(Fn f)
14472 {
14473     return internal::timed_void_function_impl<decltype(f)>(f);
14474 }
14475 
14476 }
14477 
14478 //
14479 // benchmark_session.hpp
14480 //
14481 
14482 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
14483 // https://github.com/Dobiasd/FunctionalPlus
14484 // Distributed under the Boost Software License, Version 1.0.
14485 // (See accompanying file LICENSE_1_0.txt or copy at
14486 //  http://www.boost.org/LICENSE_1_0.txt)
14487 
14488 #include <vector>
14489 #include <mutex>
14490 
14491 
14492 namespace fplus
14493 {
14494 using FunctionName = std::string;
14495 struct benchmark_function_report
14496 {
14497     std::size_t nb_calls;
14498     ExecutionTime total_time;
14499     ExecutionTime average_time;
14500     ExecutionTime deviation;
14501 };
14502 
14503 
14504 namespace internal
14505 {
14506     std::string show_benchmark_function_report(
14507         const std::map<FunctionName, benchmark_function_report> & reports);
14508 }
14509 
14510 
14511 // benchmark_session stores timings during a benchmark session
14512 // and is able to emit a report at the end
14513 class benchmark_session
14514 {
14515 public:
benchmark_session()14516     benchmark_session() : functions_times_mutex_(), functions_times_() {};
14517 
14518     // report() shall return a string with a summary of the session
14519     // Example below:
14520     // Function              |Nb calls|Total time|Av. time|Deviation|
14521     // ----------------------+--------+----------+--------+---------+
14522     // convert_charset_string|    4000|   4.942ms| 1.236us|  1.390us|
14523     // split_lines           |    1000|   4.528ms| 4.528us|  1.896us|
report() const14524     inline std::string report() const
14525     {
14526         const auto reports = report_list();
14527         return fplus::internal::show_benchmark_function_report(reports);
14528     }
14529 
report_list() const14530     std::map<FunctionName, benchmark_function_report> report_list() const
14531     {
14532         std::lock_guard<std::mutex> lock(functions_times_mutex_);
14533         std::map<FunctionName, benchmark_function_report> report;
14534         for (const auto & one_function_time : functions_times_)
14535         {
14536             report[one_function_time.first] = make_bench_report(one_function_time.second);
14537         }
14538         return report;
14539     }
14540 
store_one_time(const FunctionName & function_name,ExecutionTime time)14541     inline void store_one_time(const FunctionName & function_name, ExecutionTime time)
14542     {
14543         std::lock_guard<std::mutex> lock(functions_times_mutex_);
14544         functions_times_[function_name].push_back(time);
14545     }
14546 
14547 private:
make_bench_report(const std::vector<ExecutionTime> & times) const14548     benchmark_function_report make_bench_report(
14549         const std::vector<ExecutionTime> & times) const
14550     {
14551         benchmark_function_report result;
14552         result.nb_calls = times.size();
14553         auto mean_and_dev = fplus::mean_stddev<double>(times);
14554         result.average_time = mean_and_dev.first;
14555         result.deviation = mean_and_dev.second;
14556         result.total_time = fplus::sum(times);
14557         return result;
14558     }
14559 
14560     mutable std::mutex functions_times_mutex_;
14561     std::map<FunctionName, std::vector<ExecutionTime>> functions_times_;
14562 };
14563 
14564 namespace internal
14565 {
14566     template<typename Fn>
14567     class bench_function_impl
14568     {
14569     public:
bench_function_impl(benchmark_session & benchmark_sess,FunctionName function_name,Fn fn)14570         explicit bench_function_impl(
14571             benchmark_session & benchmark_sess,
14572             FunctionName function_name,
14573             Fn fn)
14574             : benchmark_session_(benchmark_sess)
14575             , function_name_(function_name)
14576             , fn_(fn)
14577         {};
14578 
operator ()(Args &&...args)14579         template<typename ...Args> auto operator()(Args&&... args)
14580         {
14581             return _bench_result(std::forward<Args>(args)...);
14582         }
14583 
14584     private:
14585         template<typename ...Args>
_bench_result(Args &&...args)14586         auto _bench_result(Args&&... args)
14587         {
14588             fplus::stopwatch timer;
14589             auto r = fn_(std::forward<Args>(args)...);
14590             benchmark_session_.store_one_time(function_name_, timer.elapsed());
14591             return r;
14592         }
14593 
14594         benchmark_session & benchmark_session_;
14595         FunctionName function_name_;
14596         Fn fn_;
14597     };
14598 
14599     template<typename Fn>
14600     class bench_void_function_impl
14601     {
14602     public:
bench_void_function_impl(benchmark_session & benchmark_sess,FunctionName function_name,Fn fn)14603         explicit bench_void_function_impl(
14604             benchmark_session & benchmark_sess,
14605             FunctionName function_name,
14606             Fn fn)
14607             : benchmark_session_(benchmark_sess)
14608             , function_name_(function_name)
14609             , fn_(fn)
14610         {};
14611 
operator ()(Args &&...args)14612         template<typename ...Args> auto operator()(Args&&... args)
14613         {
14614             _bench_result(std::forward<Args>(args)...);
14615         }
14616 
14617     private:
14618         template<typename ...Args>
_bench_result(Args &&...args)14619         auto _bench_result(Args&&... args)
14620         {
14621             fplus::stopwatch timer;
14622             fn_(std::forward<Args>(args)...);
14623             benchmark_session_.store_one_time(function_name_, timer.elapsed());
14624         }
14625 
14626         benchmark_session & benchmark_session_;
14627         FunctionName function_name_;
14628         Fn fn_;
14629     };
14630 
14631 } // namespace internal
14632 
14633 
14634 // API search type: make_benchmark_function : (benchmark_session, string, (a... -> b)) -> (a... -> b)
14635 // Transforms a function into a function with the *same* signature
14636 // and behavior, except that it also stores stats into the benchmark session (first parameter),
14637 // under the name given by the second parameter.
14638 // -
14639 // Notes:
14640 // Side effects: make_benchmark_function *will add side effects* to the function, since it stores data
14641 // into the benchmark session at each call.
14642 // If you intend to benchmark only one function, prefer to use the simpler "make_timed_function"
14643 // Use "make_benchmark_void_function" if your function returns void
14644 // -
14645 // Example of a minimal benchmark session (read benchmark_session_test.cpp for a full example)
14646 //     fplus::benchmark_session benchmark_sess;
14647 //     void foo() {
14648 //         auto add_bench = fplus::make_benchmark_function(benchmark_sess, "add", add);
14649 //         auto printf_bench = fplus::make_benchmark_void_function(benchmark_sess, "printf", printf);
14650 //         int forty_five = add_bench(20, add_bench(19, 6));
14651 //         int forty_two = benchmark_expression(benchmark_sess, "sub", forty_five - 3);
14652 //         printf_bench("forty_two is %i\n", forty_two);
14653 //     }
14654 //     int main() {
14655 //         foo();
14656 //         std::cout << benchmark_sess.report();
14657 //     }
14658 // This will output a report like this
14659 // Function|Nb calls|Total time|Av. time|Deviation|
14660 // --------+--------+----------+--------+---------+
14661 // printf  |       1|   0.010ms| 9.952us|  0.000us|
14662 // add     |       2|   0.000ms| 0.050us|  0.009us|
14663 // sub     |       1|   0.000ms| 0.039us|  0.000us|
14664 // -
14665 // As an alternative to make_benchmark_function, you can also benchmark an expression.
14666 // For example, in order to benchmark the following line:
14667 //     auto sorted = fplus::sort(my_vector);
14668 // Just copy/paste this expression into "bench_expression" like shown below: this expression
14669 // will then be benchmarked with the name "sort_my_vector"
14670 //     auto sorted = benchmark_expression(
14671 //         my_benchmark_session,
14672 //         "sort_my_vector",
14673 //         fplus::sort(my_vector);
14674 //     );
14675 // Notes :
14676 // benchmark_expression is a preprocessor macro that uses an immediately invoked lambda (IIL).
14677 // The expression can be copy-pasted with no modification, and it is possible to not remove the ";"
14678 // (although it also works if it is not present)
14679 // You can also benchmark an expression that returns void using benchmark_void_expression
14680 template<class Fn>
make_benchmark_function(benchmark_session & session,const FunctionName & name,Fn f)14681 auto make_benchmark_function(benchmark_session & session, const FunctionName & name, Fn f)
14682 {
14683     // transforms f into a function with the same
14684     // signature, that will store timings into the benchmark session
14685     return internal::bench_function_impl<Fn>(session, name, f);
14686 }
14687 
14688 
14689 // API search type: make_benchmark_void_function : (benchmark_session, string, (a... -> Void)) -> (a... -> Void)
14690 // Transforms a function that returns a void into a function with the *same* signature
14691 // and behavior, except that it also stores stats into the benchmark session (first parameter),
14692 // under the name given by the second parameter
14693 // Note that make_benchmark_void_function *will add side effects* to the function
14694 // (since it stores data into the benchmark session at each call)
14695 // -
14696 // Example:
14697 //     benchmark_session bench_session;
14698 //     ...
14699 //     void foo() {
14700 //         std::this_thread::sleep_for(std::chrono::milliseconds(1000));
14701 //     }
14702 //     ...
14703 //     auto foo_bench = make_benchmark_void_function(bench_session, "foo", foo);
14704 //     foo_bench();
14705 //     ...
14706 //     std::cout << benchmark_session.report();
14707 template<class Fn>
make_benchmark_void_function(benchmark_session & session,const FunctionName & name,Fn f)14708 auto make_benchmark_void_function(benchmark_session & session, const FunctionName & name, Fn f)
14709 {
14710     // transforms a void returning function into a function with the same
14711     // signature, that will store timings into the benchmark session
14712     return internal::bench_void_function_impl<Fn>(session, name, f);
14713 }
14714 
14715 #define benchmark_expression(bench_session, name, expression)      \
14716 make_benchmark_function(                                           \
14717     bench_session,                                                 \
14718     name,                                                          \
14719     [&]() { return expression; }                                   \
14720 )();
14721 
14722 #define benchmark_void_expression(bench_session, name, expression) \
14723 make_benchmark_void_function(                                      \
14724     bench_session,                                                 \
14725     name,                                                          \
14726     [&]() { expression; }                                          \
14727 )();
14728 
14729 
14730 namespace internal
14731 {
show_table(const std::vector<std::vector<std::string>> & rows)14732     inline std::string show_table(const std::vector<std::vector<std::string>>& rows)
14733     {
14734         if (rows.empty() || rows[0].empty())
14735             return "";
14736 
14737         const std::vector<std::size_t> columns_width = [&]() {
14738             auto string_size = [](const std::string & s) -> std::size_t { return s.size(); };
14739             auto largest_string_size = [&](const std::vector<std::string> & strings) -> std::size_t {
14740                 return string_size(fplus::maximum_on(string_size, strings));
14741             };
14742             return fplus::transform(largest_string_size, fplus::transpose(rows));
14743         }();
14744 
14745         auto show_one_element = [](const std::pair<std::string, std::size_t> & elem_and_width) {
14746             const std::string & element = elem_and_width.first;
14747             const auto col_width = elem_and_width.second;
14748             bool is_number = element.size() > 0 && isdigit(element[0]);
14749             if (is_number)
14750                 return fplus::show_fill_left(' ', col_width, element) + "|";
14751             else
14752                 return fplus::show_fill_right(' ', col_width, element) + "|";
14753         };
14754 
14755         auto show_one_separator = [](std::size_t col_width) {
14756             return fplus::show_fill_left('-', col_width, "") + "+";
14757         };
14758 
14759         auto show_one_row = [&](const std::vector<std::string> & row) {
14760             return fplus::sum(fplus::transform(
14761                 show_one_element,
14762                 fplus::zip(row, columns_width)));
14763         };
14764 
14765         auto firstrow_separator = fplus::sum(fplus::transform(show_one_separator, columns_width));
14766         auto rows_formatted = fplus::transform(show_one_row, rows);
14767         auto rows_separated = fplus::insert_at_idx(1, firstrow_separator, rows_formatted);
14768         return fplus::join( std::string("\n"), rows_separated) + "\n";
14769     }
14770 
make_ordered_reports(const std::map<FunctionName,benchmark_function_report> & report_map)14771     inline std::vector< std::pair<FunctionName, benchmark_function_report> > make_ordered_reports(
14772         const std::map<FunctionName, benchmark_function_report> & report_map)
14773     {
14774         auto report_pairs = fplus::map_to_pairs(report_map);
14775         auto report_pairs_sorted = fplus::sort_by([](const auto &a, const auto &b) {
14776             return a.second.total_time > b.second.total_time;
14777         }, report_pairs);
14778         return report_pairs_sorted;
14779     }
14780 
show_benchmark_function_report(const std::map<FunctionName,benchmark_function_report> & reports)14781     inline std::string show_benchmark_function_report(const std::map<FunctionName, benchmark_function_report> & reports)
14782     {
14783         auto ordered_reports = make_ordered_reports(reports);
14784         auto my_show_time_ms = [](double time) -> std::string {
14785             std::stringstream ss;
14786             ss << std::fixed << std::setprecision(3);
14787             ss << (time * 1000.);
14788             return ss.str() + "ms";
14789         };
14790         auto my_show_time_us = [](double time) -> std::string {
14791             std::stringstream ss;
14792             ss << std::fixed << std::setprecision(3);
14793             ss << (time * 1000000.);
14794             return ss.str() + "us";
14795         };
14796 
14797         std::vector<std::string> header_row{ {
14798                 "Function", "Nb calls", "Total time", "Av. time", "Deviation"
14799             } };
14800         auto value_rows = fplus::transform([&](const auto & kv) {
14801                 const auto & report = kv.second;
14802                 const auto & function_name = kv.first;
14803                 std::vector<std::string> row;
14804                 row.push_back(function_name);
14805                 row.push_back(fplus::show(report.nb_calls));
14806                 row.push_back(my_show_time_ms(report.total_time));
14807                 row.push_back(my_show_time_us(report.average_time));
14808                 row.push_back(my_show_time_us(report.deviation));
14809                 return row;
14810             },
14811             ordered_reports);
14812 
14813         return fplus::internal::show_table(fplus::insert_at_idx(0, header_row, value_rows));
14814     }
14815 } // namespace internal
14816 
14817 }
14818 
14819 
14820 //
14821 // curry.hpp
14822 //
14823 
14824 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
14825 // https://github.com/Dobiasd/FunctionalPlus
14826 // Distributed under the Boost Software License, Version 1.0.
14827 // (See accompanying file LICENSE_1_0.txt or copy at
14828 //  http://www.boost.org/LICENSE_1_0.txt)
14829 
14830 
14831 namespace fplus
14832 {
14833 namespace curry
14834 {
14835 
14836 // Currying.
14837 // Allow to generically bind parameters one by one.
14838 
14839 #define fplus_curry_define_fn_0(fplus_curry_define_fn_0_name) \
14840 inline auto fplus_curry_define_fn_0_name() \
14841 { \
14842     return [](auto&& fplus_curry_p1) \
14843     { \
14844         return fplus::fplus_curry_define_fn_0_name(std::forward<decltype(fplus_curry_p1)>(fplus_curry_p1)); \
14845     }; \
14846 }
14847 
14848 #define fplus_curry_define_fn_1(fplus_curry_define_fn_1_name) \
14849 template <typename P1> \
14850 auto fplus_curry_define_fn_1_name(P1 p1) \
14851 { \
14852     return [p1](auto&& fplus_curry_p2) \
14853     { \
14854         return fplus::fplus_curry_define_fn_1_name(p1, std::forward<decltype(fplus_curry_p2)>(fplus_curry_p2)); \
14855     }; \
14856 }
14857 
14858 #define fplus_curry_define_fn_2(fplus_curry_define_fn_2_name) \
14859 template <typename P1> \
14860 auto fplus_curry_define_fn_2_name(P1 p1) \
14861 { \
14862     return [p1](const auto& fplus_curry_p2) \
14863     { \
14864         return [p1, fplus_curry_p2](auto&& fplus_curry_p3) \
14865         { \
14866             return fplus::fplus_curry_define_fn_2_name(p1, fplus_curry_p2, std::forward<decltype(fplus_curry_p3)>(fplus_curry_p3)); \
14867         }; \
14868     }; \
14869 }
14870 
14871 #define fplus_curry_define_fn_3(fplus_curry_define_fn_3_name) \
14872 template <typename P1> \
14873 auto fplus_curry_define_fn_3_name(P1 p1) \
14874 { \
14875     return [p1](const auto& fplus_curry_p2) \
14876     { \
14877         return [p1, fplus_curry_p2](const auto& fplus_curry_p3) \
14878         { \
14879             return [p1, fplus_curry_p2, fplus_curry_p3](auto&& fplus_curry_p4) \
14880             { \
14881                 return fplus::fplus_curry_define_fn_3_name(p1, fplus_curry_p2, fplus_curry_p3, std::forward<decltype(fplus_curry_p4)>(fplus_curry_p4)); \
14882             }; \
14883         }; \
14884     }; \
14885 }
14886 
14887 #define fplus_curry_define_fn_4(fplus_curry_define_fn_4_name) \
14888 template <typename P1> \
14889 auto fplus_curry_define_fn_4_name(P1 p1) \
14890 { \
14891 return [p1](const auto& fplus_curry_p2) \
14892     { \
14893         return [p1, fplus_curry_p2](const auto& fplus_curry_p3) \
14894         { \
14895             return [p1, fplus_curry_p2, fplus_curry_p3](const auto& fplus_curry_p4) \
14896             { \
14897                 return [p1, fplus_curry_p2, fplus_curry_p3, fplus_curry_p4](auto&& fplus_curry_p5) \
14898                 { \
14899                     return fplus::fplus_curry_define_fn_4_name(p1, fplus_curry_p2, fplus_curry_p3, fplus_curry_p4, std::forward<decltype(fplus_curry_p5)>(fplus_curry_p5)); \
14900                 }; \
14901             }; \
14902         }; \
14903     }; \
14904 }
14905 
14906 
14907 
14908 //
14909 // curry_instances.autogenerated_defines
14910 //
14911 
14912 // THIS FILE WAS GENERATED AUTOMATICALLY. DO NOT EDIT.
14913 fplus_curry_define_fn_0(identity)
14914 fplus_curry_define_fn_1(is_equal)
14915 fplus_curry_define_fn_1(is_not_equal)
14916 fplus_curry_define_fn_1(is_less)
14917 fplus_curry_define_fn_1(is_less_or_equal)
14918 fplus_curry_define_fn_1(is_greater)
14919 fplus_curry_define_fn_1(is_greater_or_equal)
14920 fplus_curry_define_fn_1(xor_bools)
14921 fplus_curry_define_fn_0(is_just)
14922 fplus_curry_define_fn_0(is_nothing)
14923 fplus_curry_define_fn_0(unsafe_get_just)
14924 fplus_curry_define_fn_0(just_with_default)
14925 fplus_curry_define_fn_1(throw_on_nothing)
14926 fplus_curry_define_fn_0(just)
14927 fplus_curry_define_fn_1(as_just_if)
14928 fplus_curry_define_fn_0(maybe_to_seq)
14929 fplus_curry_define_fn_0(singleton_seq_as_maybe)
14930 fplus_curry_define_fn_1(lift_maybe)
14931 fplus_curry_define_fn_2(lift_maybe_def)
14932 fplus_curry_define_fn_2(lift_maybe_2)
14933 fplus_curry_define_fn_3(lift_maybe_2_def)
14934 fplus_curry_define_fn_1(and_then_maybe)
14935 fplus_curry_define_fn_0(flatten_maybe)
14936 fplus_curry_define_fn_0(is_even)
14937 fplus_curry_define_fn_0(is_odd)
14938 fplus_curry_define_fn_0(is_empty)
14939 fplus_curry_define_fn_0(is_not_empty)
14940 fplus_curry_define_fn_0(size_of_cont)
14941 fplus_curry_define_fn_0(convert)
14942 fplus_curry_define_fn_0(convert_elems)
14943 fplus_curry_define_fn_0(convert_container)
14944 fplus_curry_define_fn_0(convert_container_and_elems)
14945 fplus_curry_define_fn_2(get_segment)
14946 fplus_curry_define_fn_2(set_segment)
14947 fplus_curry_define_fn_2(remove_segment)
14948 fplus_curry_define_fn_2(insert_at)
14949 fplus_curry_define_fn_1(elem_at_idx)
14950 fplus_curry_define_fn_1(elem_at_idx_maybe)
14951 fplus_curry_define_fn_1(elems_at_idxs)
14952 fplus_curry_define_fn_1(transform)
14953 fplus_curry_define_fn_1(transform_convert)
14954 fplus_curry_define_fn_1(transform_inner)
14955 fplus_curry_define_fn_0(reverse)
14956 fplus_curry_define_fn_1(take)
14957 fplus_curry_define_fn_1(take_exact)
14958 fplus_curry_define_fn_1(take_cyclic)
14959 fplus_curry_define_fn_1(drop)
14960 fplus_curry_define_fn_1(take_last)
14961 fplus_curry_define_fn_1(drop_last)
14962 fplus_curry_define_fn_1(drop_exact)
14963 fplus_curry_define_fn_1(take_while)
14964 fplus_curry_define_fn_1(take_last_while)
14965 fplus_curry_define_fn_1(drop_while)
14966 fplus_curry_define_fn_1(drop_last_while)
14967 fplus_curry_define_fn_2(fold_left)
14968 fplus_curry_define_fn_2(reduce)
14969 fplus_curry_define_fn_1(fold_left_1)
14970 fplus_curry_define_fn_1(reduce_1)
14971 fplus_curry_define_fn_2(fold_right)
14972 fplus_curry_define_fn_1(fold_right_1)
14973 fplus_curry_define_fn_2(scan_left)
14974 fplus_curry_define_fn_1(scan_left_1)
14975 fplus_curry_define_fn_2(scan_right)
14976 fplus_curry_define_fn_1(scan_right_1)
14977 fplus_curry_define_fn_0(sum)
14978 fplus_curry_define_fn_0(product)
14979 fplus_curry_define_fn_1(append_elem)
14980 fplus_curry_define_fn_1(prepend_elem)
14981 fplus_curry_define_fn_1(append)
14982 fplus_curry_define_fn_1(append_convert)
14983 fplus_curry_define_fn_0(concat)
14984 fplus_curry_define_fn_1(interweave)
14985 fplus_curry_define_fn_0(unweave)
14986 fplus_curry_define_fn_1(sort_by)
14987 fplus_curry_define_fn_1(sort_on)
14988 fplus_curry_define_fn_0(sort)
14989 fplus_curry_define_fn_1(stable_sort_by)
14990 fplus_curry_define_fn_1(stable_sort_on)
14991 fplus_curry_define_fn_0(stable_sort)
14992 fplus_curry_define_fn_2(partial_sort_by)
14993 fplus_curry_define_fn_2(partial_sort_on)
14994 fplus_curry_define_fn_1(partial_sort)
14995 fplus_curry_define_fn_2(nth_element_by)
14996 fplus_curry_define_fn_2(nth_element_on)
14997 fplus_curry_define_fn_1(nth_element)
14998 fplus_curry_define_fn_1(unique_by)
14999 fplus_curry_define_fn_1(unique_on)
15000 fplus_curry_define_fn_0(unique)
15001 fplus_curry_define_fn_1(intersperse)
15002 fplus_curry_define_fn_1(join)
15003 fplus_curry_define_fn_1(join_elem)
15004 fplus_curry_define_fn_1(is_elem_of_by)
15005 fplus_curry_define_fn_1(is_elem_of)
15006 fplus_curry_define_fn_1(nub_by)
15007 fplus_curry_define_fn_1(nub_on)
15008 fplus_curry_define_fn_0(nub)
15009 fplus_curry_define_fn_1(all_unique_by_eq)
15010 fplus_curry_define_fn_1(all_unique_on)
15011 fplus_curry_define_fn_0(all_unique)
15012 fplus_curry_define_fn_1(is_strictly_sorted_by)
15013 fplus_curry_define_fn_1(is_strictly_sorted_on)
15014 fplus_curry_define_fn_0(is_strictly_sorted)
15015 fplus_curry_define_fn_1(is_sorted_by)
15016 fplus_curry_define_fn_1(is_sorted_on)
15017 fplus_curry_define_fn_0(is_sorted)
15018 fplus_curry_define_fn_1(is_prefix_of)
15019 fplus_curry_define_fn_1(is_suffix_of)
15020 fplus_curry_define_fn_1(all_by)
15021 fplus_curry_define_fn_0(all)
15022 fplus_curry_define_fn_1(all_the_same_by)
15023 fplus_curry_define_fn_1(all_the_same_on)
15024 fplus_curry_define_fn_0(all_the_same)
15025 fplus_curry_define_fn_2(numbers_step)
15026 fplus_curry_define_fn_1(numbers)
15027 fplus_curry_define_fn_0(singleton_seq)
15028 fplus_curry_define_fn_0(all_idxs)
15029 fplus_curry_define_fn_0(init)
15030 fplus_curry_define_fn_0(tail)
15031 fplus_curry_define_fn_0(head)
15032 fplus_curry_define_fn_0(last)
15033 fplus_curry_define_fn_0(mean_stddev)
15034 fplus_curry_define_fn_1(count_occurrences_by)
15035 fplus_curry_define_fn_0(count_occurrences)
15036 fplus_curry_define_fn_2(lexicographical_less_by)
15037 fplus_curry_define_fn_1(lexicographical_less)
15038 fplus_curry_define_fn_0(lexicographical_sort)
15039 fplus_curry_define_fn_1(replicate)
15040 fplus_curry_define_fn_2(instead_of_if)
15041 fplus_curry_define_fn_2(instead_of_if_empty)
15042 fplus_curry_define_fn_0(is_ok)
15043 fplus_curry_define_fn_0(is_error)
15044 fplus_curry_define_fn_0(unsafe_get_ok)
15045 fplus_curry_define_fn_0(unsafe_get_error)
15046 fplus_curry_define_fn_1(ok_with_default)
15047 fplus_curry_define_fn_0(ok)
15048 fplus_curry_define_fn_0(error)
15049 fplus_curry_define_fn_0(to_maybe)
15050 fplus_curry_define_fn_1(from_maybe)
15051 fplus_curry_define_fn_1(throw_on_error)
15052 fplus_curry_define_fn_1(lift_result)
15053 fplus_curry_define_fn_2(lift_result_both)
15054 fplus_curry_define_fn_2(unify_result)
15055 fplus_curry_define_fn_1(and_then_result)
15056 fplus_curry_define_fn_1(keep_if)
15057 fplus_curry_define_fn_1(drop_if)
15058 fplus_curry_define_fn_1(without)
15059 fplus_curry_define_fn_1(without_any)
15060 fplus_curry_define_fn_1(keep_if_with_idx)
15061 fplus_curry_define_fn_1(drop_if_with_idx)
15062 fplus_curry_define_fn_1(keep_by_idx)
15063 fplus_curry_define_fn_1(drop_by_idx)
15064 fplus_curry_define_fn_1(keep_idxs)
15065 fplus_curry_define_fn_1(drop_idxs)
15066 fplus_curry_define_fn_1(drop_idx)
15067 fplus_curry_define_fn_0(justs)
15068 fplus_curry_define_fn_0(oks)
15069 fplus_curry_define_fn_0(errors)
15070 fplus_curry_define_fn_1(trim_left)
15071 fplus_curry_define_fn_1(trim_token_left)
15072 fplus_curry_define_fn_1(trim_right_by)
15073 fplus_curry_define_fn_1(trim_right)
15074 fplus_curry_define_fn_1(trim_token_right)
15075 fplus_curry_define_fn_1(trim_by)
15076 fplus_curry_define_fn_1(trim)
15077 fplus_curry_define_fn_1(trim_token)
15078 fplus_curry_define_fn_1(adjacent_keep_snd_if)
15079 fplus_curry_define_fn_1(adjacent_drop_fst_if)
15080 fplus_curry_define_fn_1(adjacent_drop_snd_if)
15081 fplus_curry_define_fn_1(adjacent_keep_fst_if)
15082 fplus_curry_define_fn_1(generate_by_idx)
15083 fplus_curry_define_fn_1(repeat)
15084 fplus_curry_define_fn_1(infixes)
15085 fplus_curry_define_fn_3(carthesian_product_with_where)
15086 fplus_curry_define_fn_2(carthesian_product_with)
15087 fplus_curry_define_fn_2(carthesian_product_where)
15088 fplus_curry_define_fn_1(carthesian_product)
15089 fplus_curry_define_fn_1(carthesian_product_n)
15090 fplus_curry_define_fn_1(permutations)
15091 fplus_curry_define_fn_1(combinations)
15092 fplus_curry_define_fn_1(combinations_with_replacement)
15093 fplus_curry_define_fn_0(power_set)
15094 fplus_curry_define_fn_2(iterate)
15095 fplus_curry_define_fn_1(iterate_maybe)
15096 fplus_curry_define_fn_1(adjacent_difference_by)
15097 fplus_curry_define_fn_0(adjacent_difference)
15098 fplus_curry_define_fn_0(rotate_left)
15099 fplus_curry_define_fn_0(rotate_right)
15100 fplus_curry_define_fn_0(rotations_left)
15101 fplus_curry_define_fn_0(rotations_right)
15102 fplus_curry_define_fn_2(fill_left)
15103 fplus_curry_define_fn_2(fill_right)
15104 fplus_curry_define_fn_0(inits)
15105 fplus_curry_define_fn_0(tails)
15106 fplus_curry_define_fn_1(apply_to_pair)
15107 fplus_curry_define_fn_2(zip_with)
15108 fplus_curry_define_fn_3(zip_with_3)
15109 fplus_curry_define_fn_4(zip_with_defaults)
15110 fplus_curry_define_fn_1(zip)
15111 fplus_curry_define_fn_1(zip_repeat)
15112 fplus_curry_define_fn_0(unzip)
15113 fplus_curry_define_fn_0(fst)
15114 fplus_curry_define_fn_0(snd)
15115 fplus_curry_define_fn_1(transform_fst)
15116 fplus_curry_define_fn_1(transform_snd)
15117 fplus_curry_define_fn_2(transform_pair)
15118 fplus_curry_define_fn_0(swap_pair_elems)
15119 fplus_curry_define_fn_0(swap_pairs_elems)
15120 fplus_curry_define_fn_0(adjacent_pairs)
15121 fplus_curry_define_fn_0(overlapping_pairs)
15122 fplus_curry_define_fn_0(overlapping_pairs_cyclic)
15123 fplus_curry_define_fn_0(enumerate)
15124 fplus_curry_define_fn_4(inner_product_with)
15125 fplus_curry_define_fn_2(inner_product)
15126 fplus_curry_define_fn_2(first_mismatch_idx_by)
15127 fplus_curry_define_fn_2(first_mismatch_by)
15128 fplus_curry_define_fn_2(first_mismatch_idx_on)
15129 fplus_curry_define_fn_2(first_mismatch_on)
15130 fplus_curry_define_fn_2(first_mismatch_idx)
15131 fplus_curry_define_fn_2(first_mismatch)
15132 fplus_curry_define_fn_2(first_match_idx_by)
15133 fplus_curry_define_fn_2(first_match_by)
15134 fplus_curry_define_fn_2(first_match_idx_on)
15135 fplus_curry_define_fn_2(first_match_on)
15136 fplus_curry_define_fn_2(first_match_idx)
15137 fplus_curry_define_fn_2(first_match)
15138 fplus_curry_define_fn_2(is_in_interval)
15139 fplus_curry_define_fn_2(is_in_interval_around)
15140 fplus_curry_define_fn_2(is_in_open_interval)
15141 fplus_curry_define_fn_2(is_in_open_interval_around)
15142 fplus_curry_define_fn_2(is_in_closed_interval)
15143 fplus_curry_define_fn_4(reference_interval)
15144 fplus_curry_define_fn_2(clamp)
15145 fplus_curry_define_fn_0(is_negative)
15146 fplus_curry_define_fn_0(is_positive)
15147 fplus_curry_define_fn_0(abs)
15148 fplus_curry_define_fn_1(abs_diff)
15149 fplus_curry_define_fn_0(square)
15150 fplus_curry_define_fn_0(cube)
15151 fplus_curry_define_fn_0(sign)
15152 fplus_curry_define_fn_0(sign_with_zero)
15153 fplus_curry_define_fn_0(integral_cast_throw)
15154 fplus_curry_define_fn_0(integral_cast_clamp)
15155 fplus_curry_define_fn_0(round)
15156 fplus_curry_define_fn_0(floor)
15157 fplus_curry_define_fn_1(floor_to_int_mult)
15158 fplus_curry_define_fn_1(ceil_to_int_mult)
15159 fplus_curry_define_fn_0(ceil)
15160 fplus_curry_define_fn_1(int_power)
15161 fplus_curry_define_fn_2(min_2_on)
15162 fplus_curry_define_fn_2(max_2_on)
15163 fplus_curry_define_fn_1(min_2)
15164 fplus_curry_define_fn_1(max_2)
15165 fplus_curry_define_fn_0(deg_to_rad)
15166 fplus_curry_define_fn_0(rad_to_deg)
15167 fplus_curry_define_fn_2(normalize_min_max)
15168 fplus_curry_define_fn_2(normalize_mean_stddev)
15169 fplus_curry_define_fn_0(standardize)
15170 fplus_curry_define_fn_1(histogram_using_intervals)
15171 fplus_curry_define_fn_2(generate_consecutive_intervals)
15172 fplus_curry_define_fn_3(histogram)
15173 fplus_curry_define_fn_1(modulo_chain)
15174 fplus_curry_define_fn_2(line_equation)
15175 fplus_curry_define_fn_1(find_first_by)
15176 fplus_curry_define_fn_1(find_last_by)
15177 fplus_curry_define_fn_1(find_first_idx_by)
15178 fplus_curry_define_fn_1(find_last_idx_by)
15179 fplus_curry_define_fn_1(find_first_idx)
15180 fplus_curry_define_fn_1(find_last_idx)
15181 fplus_curry_define_fn_1(find_all_idxs_by)
15182 fplus_curry_define_fn_1(find_all_idxs_of)
15183 fplus_curry_define_fn_1(find_all_instances_of_token)
15184 fplus_curry_define_fn_1(find_all_instances_of_token_non_overlapping)
15185 fplus_curry_define_fn_1(find_first_instance_of_token)
15186 fplus_curry_define_fn_1(set_includes)
15187 fplus_curry_define_fn_1(unordered_set_includes)
15188 fplus_curry_define_fn_1(set_merge)
15189 fplus_curry_define_fn_1(unordered_set_merge)
15190 fplus_curry_define_fn_1(set_intersection)
15191 fplus_curry_define_fn_1(unordered_set_intersection)
15192 fplus_curry_define_fn_1(set_is_disjoint)
15193 fplus_curry_define_fn_1(unordered_set_is_disjoint)
15194 fplus_curry_define_fn_1(set_difference)
15195 fplus_curry_define_fn_1(unordered_set_difference)
15196 fplus_curry_define_fn_1(set_symmetric_difference)
15197 fplus_curry_define_fn_1(unordered_set_symmetric_difference)
15198 fplus_curry_define_fn_0(sets_intersection)
15199 fplus_curry_define_fn_0(unordered_sets_intersection)
15200 fplus_curry_define_fn_1(any_by)
15201 fplus_curry_define_fn_0(any)
15202 fplus_curry_define_fn_1(none_by)
15203 fplus_curry_define_fn_0(none)
15204 fplus_curry_define_fn_1(minimum_idx_by)
15205 fplus_curry_define_fn_1(minimum_idx_by_maybe)
15206 fplus_curry_define_fn_1(maximum_idx_by)
15207 fplus_curry_define_fn_1(maximum_idx_by_maybe)
15208 fplus_curry_define_fn_0(minimum_idx)
15209 fplus_curry_define_fn_0(minimum_idx_maybe)
15210 fplus_curry_define_fn_0(maximum_idx)
15211 fplus_curry_define_fn_0(maximum_idx_maybe)
15212 fplus_curry_define_fn_1(minimum_idx_on)
15213 fplus_curry_define_fn_1(minimum_idx_on_maybe)
15214 fplus_curry_define_fn_1(maximum_idx_on)
15215 fplus_curry_define_fn_1(maximum_idx_on_maybe)
15216 fplus_curry_define_fn_1(minimum_by)
15217 fplus_curry_define_fn_1(minimum_by_maybe)
15218 fplus_curry_define_fn_1(maximum_by)
15219 fplus_curry_define_fn_1(maximum_by_maybe)
15220 fplus_curry_define_fn_0(minimum)
15221 fplus_curry_define_fn_0(minimum_maybe)
15222 fplus_curry_define_fn_0(maximum)
15223 fplus_curry_define_fn_0(maximum_maybe)
15224 fplus_curry_define_fn_1(minimum_on)
15225 fplus_curry_define_fn_1(minimum_on_maybe)
15226 fplus_curry_define_fn_1(maximum_on)
15227 fplus_curry_define_fn_1(maximum_on_maybe)
15228 fplus_curry_define_fn_0(mean)
15229 fplus_curry_define_fn_0(mean_obj_div_size_t)
15230 fplus_curry_define_fn_0(mean_obj_div_double)
15231 fplus_curry_define_fn_0(mean_using_doubles)
15232 fplus_curry_define_fn_0(median)
15233 fplus_curry_define_fn_1(all_unique_by_less)
15234 fplus_curry_define_fn_0(all_unique_less)
15235 fplus_curry_define_fn_1(is_infix_of)
15236 fplus_curry_define_fn_1(is_subsequence_of)
15237 fplus_curry_define_fn_1(count_if)
15238 fplus_curry_define_fn_1(count)
15239 fplus_curry_define_fn_1(is_unique_in_by)
15240 fplus_curry_define_fn_1(is_unique_in)
15241 fplus_curry_define_fn_1(is_permutation_of)
15242 fplus_curry_define_fn_1(fill_pigeonholes_to)
15243 fplus_curry_define_fn_0(fill_pigeonholes)
15244 fplus_curry_define_fn_1(fill_pigeonholes_bool_to)
15245 fplus_curry_define_fn_0(fill_pigeonholes_bool)
15246 fplus_curry_define_fn_0(present_in_all)
15247 fplus_curry_define_fn_1(elem_at_idx_or_nothing)
15248 fplus_curry_define_fn_2(elem_at_idx_or_constant)
15249 fplus_curry_define_fn_1(elem_at_idx_or_replicate)
15250 fplus_curry_define_fn_1(elem_at_idx_or_wrap)
15251 fplus_curry_define_fn_2(extrapolate_replicate)
15252 fplus_curry_define_fn_2(extrapolate_wrap)
15253 fplus_curry_define_fn_1(elem_at_float_idx)
15254 fplus_curry_define_fn_0(pairs_to_map)
15255 fplus_curry_define_fn_0(pairs_to_map_grouped)
15256 fplus_curry_define_fn_0(pairs_to_unordered_map_grouped)
15257 fplus_curry_define_fn_0(map_to_pairs)
15258 fplus_curry_define_fn_1(transform_map_values)
15259 fplus_curry_define_fn_2(map_union_with)
15260 fplus_curry_define_fn_1(map_union)
15261 fplus_curry_define_fn_0(map_grouped_to_pairs)
15262 fplus_curry_define_fn_0(get_map_keys)
15263 fplus_curry_define_fn_0(get_map_values)
15264 fplus_curry_define_fn_0(swap_keys_and_values)
15265 fplus_curry_define_fn_1(create_map)
15266 fplus_curry_define_fn_1(create_map_with)
15267 fplus_curry_define_fn_1(create_map_grouped)
15268 fplus_curry_define_fn_1(create_unordered_map)
15269 fplus_curry_define_fn_1(create_unordered_map_with)
15270 fplus_curry_define_fn_1(create_unordered_map_grouped)
15271 fplus_curry_define_fn_1(get_from_map)
15272 fplus_curry_define_fn_1(get_from_map_unsafe)
15273 fplus_curry_define_fn_2(get_from_map_with_def)
15274 fplus_curry_define_fn_1(get_first_from_map)
15275 fplus_curry_define_fn_1(get_first_from_map_unsafe)
15276 fplus_curry_define_fn_2(get_first_from_map_with_def)
15277 fplus_curry_define_fn_1(map_contains)
15278 fplus_curry_define_fn_1(map_keep_if)
15279 fplus_curry_define_fn_1(map_drop_if)
15280 fplus_curry_define_fn_1(map_keep)
15281 fplus_curry_define_fn_1(map_drop)
15282 fplus_curry_define_fn_1(map_keep_if_value)
15283 fplus_curry_define_fn_1(map_drop_if_value)
15284 fplus_curry_define_fn_1(map_keep_values)
15285 fplus_curry_define_fn_1(map_drop_values)
15286 fplus_curry_define_fn_1(map_pluck)
15287 fplus_curry_define_fn_1(choose)
15288 fplus_curry_define_fn_2(choose_by)
15289 fplus_curry_define_fn_1(choose_lazy)
15290 fplus_curry_define_fn_2(choose_by_lazy)
15291 fplus_curry_define_fn_1(choose_def)
15292 fplus_curry_define_fn_2(choose_by_def)
15293 fplus_curry_define_fn_1(choose_def_lazy)
15294 fplus_curry_define_fn_2(choose_by_def_lazy)
15295 fplus_curry_define_fn_1(group_by)
15296 fplus_curry_define_fn_1(group_on)
15297 fplus_curry_define_fn_1(group_on_labeled)
15298 fplus_curry_define_fn_0(group)
15299 fplus_curry_define_fn_1(group_globally_by)
15300 fplus_curry_define_fn_1(group_globally_on)
15301 fplus_curry_define_fn_1(group_globally_on_labeled)
15302 fplus_curry_define_fn_0(group_globally)
15303 fplus_curry_define_fn_1(cluster_by)
15304 fplus_curry_define_fn_2(split_by)
15305 fplus_curry_define_fn_1(split_by_keep_separators)
15306 fplus_curry_define_fn_2(split)
15307 fplus_curry_define_fn_2(split_one_of)
15308 fplus_curry_define_fn_1(split_keep_separators)
15309 fplus_curry_define_fn_1(split_at_idx)
15310 fplus_curry_define_fn_2(insert_at_idx)
15311 fplus_curry_define_fn_1(partition)
15312 fplus_curry_define_fn_1(split_at_idxs)
15313 fplus_curry_define_fn_1(split_every)
15314 fplus_curry_define_fn_2(split_by_token)
15315 fplus_curry_define_fn_1(run_length_encode_by)
15316 fplus_curry_define_fn_0(run_length_encode)
15317 fplus_curry_define_fn_0(run_length_decode)
15318 fplus_curry_define_fn_1(span)
15319 fplus_curry_define_fn_2(divvy)
15320 fplus_curry_define_fn_1(aperture)
15321 fplus_curry_define_fn_1(stride)
15322 fplus_curry_define_fn_1(winsorize)
15323 fplus_curry_define_fn_1(separate_on)
15324 fplus_curry_define_fn_0(separate)
15325 fplus_curry_define_fn_1(transform_with_idx)
15326 fplus_curry_define_fn_1(transform_and_keep_justs)
15327 fplus_curry_define_fn_1(transform_and_keep_oks)
15328 fplus_curry_define_fn_1(transform_and_concat)
15329 fplus_curry_define_fn_1(replicate_elems)
15330 fplus_curry_define_fn_0(interleave)
15331 fplus_curry_define_fn_0(transpose)
15332 fplus_curry_define_fn_1(shuffle)
15333 fplus_curry_define_fn_2(sample)
15334 fplus_curry_define_fn_1(random_element)
15335 fplus_curry_define_fn_2(random_elements)
15336 fplus_curry_define_fn_1(apply_functions)
15337 fplus_curry_define_fn_2(apply_function_n_times)
15338 fplus_curry_define_fn_1(transform_parallelly)
15339 fplus_curry_define_fn_2(transform_parallelly_n_threads)
15340 fplus_curry_define_fn_2(reduce_parallelly)
15341 fplus_curry_define_fn_3(reduce_parallelly_n_threads)
15342 fplus_curry_define_fn_1(reduce_1_parallelly)
15343 fplus_curry_define_fn_2(reduce_1_parallelly_n_threads)
15344 fplus_curry_define_fn_1(keep_if_parallelly)
15345 fplus_curry_define_fn_2(keep_if_parallelly_n_threads)
15346 fplus_curry_define_fn_3(transform_reduce)
15347 fplus_curry_define_fn_2(transform_reduce_1)
15348 fplus_curry_define_fn_3(transform_reduce_parallelly)
15349 fplus_curry_define_fn_4(transform_reduce_parallelly_n_threads)
15350 fplus_curry_define_fn_2(transform_reduce_1_parallelly)
15351 fplus_curry_define_fn_3(transform_reduce_1_parallelly_n_threads)
15352 fplus_curry_define_fn_1(read_value_with_default)
15353 fplus_curry_define_fn_2(replace_if)
15354 fplus_curry_define_fn_2(replace_elem_at_idx)
15355 fplus_curry_define_fn_2(replace_elems)
15356 fplus_curry_define_fn_2(replace_tokens)
15357 fplus_curry_define_fn_0(show)
15358 fplus_curry_define_fn_3(show_cont_with_frame_and_newlines)
15359 fplus_curry_define_fn_3(show_cont_with_frame)
15360 fplus_curry_define_fn_1(show_cont_with)
15361 fplus_curry_define_fn_0(show_cont)
15362 fplus_curry_define_fn_0(show_maybe)
15363 fplus_curry_define_fn_0(show_result)
15364 fplus_curry_define_fn_2(show_float)
15365 fplus_curry_define_fn_3(show_float_fill_left)
15366 fplus_curry_define_fn_2(show_fill_left)
15367 fplus_curry_define_fn_2(show_fill_right)
15368 fplus_curry_define_fn_0(is_letter_or_digit)
15369 fplus_curry_define_fn_0(is_whitespace)
15370 fplus_curry_define_fn_0(is_line_break)
15371 fplus_curry_define_fn_0(clean_newlines)
15372 fplus_curry_define_fn_1(split_words)
15373 fplus_curry_define_fn_1(split_lines)
15374 fplus_curry_define_fn_0(trim_whitespace_left)
15375 fplus_curry_define_fn_0(trim_whitespace_right)
15376 fplus_curry_define_fn_0(trim_whitespace)
15377 fplus_curry_define_fn_0(to_lower_case)
15378 fplus_curry_define_fn_1(to_lower_case_loc)
15379 fplus_curry_define_fn_0(to_upper_case)
15380 fplus_curry_define_fn_1(to_upper_case_loc)
15381 fplus_curry_define_fn_2(to_string_fill_left)
15382 fplus_curry_define_fn_2(to_string_fill_right)
15383 fplus_curry_define_fn_1(trees_from_sequence)
15384 fplus_curry_define_fn_1(are_trees_equal)
15385 fplus_curry_define_fn_0(tree_size)
15386 fplus_curry_define_fn_0(tree_depth)
15387 fplus_curry_define_fn_0(flatten_tree_depth_first)
15388 fplus_curry_define_fn_0(flatten_tree_breadth_first)
15389 fplus_curry_define_fn_0(show_timed)
15390 fplus_curry_define_fn_0(make_timed_function)
15391 fplus_curry_define_fn_0(make_timed_void_function)
15392 
15393 } // namespace curry
15394 } // namespace fplus
15395 
15396 //
15397 // fwd.hpp
15398 //
15399 
15400 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
15401 // https://github.com/Dobiasd/FunctionalPlus
15402 // Distributed under the Boost Software License, Version 1.0.
15403 // (See accompanying file LICENSE_1_0.txt or copy at
15404 //  http://www.boost.org/LICENSE_1_0.txt)
15405 
15406 
15407 namespace fplus
15408 {
15409 namespace fwd
15410 {
15411 
15412 // Partial currying.
15413 // Allow to generically bind all but parameters except the last one.
15414 // The lambda paramter ist named fplus_fwd_x instead of x
15415 // because gcc can produce unjustified shadow warnings. see:
15416 // http://stackoverflow.com/questions/41208811/parameter-of-returned-generic-lambda-allegedly-shadows-parameter-of-free-functio
15417 #define fplus_fwd_define_fn_0(fplus_fwd_define_fn_0_name) \
15418 inline auto fplus_fwd_define_fn_0_name() \
15419 { \
15420     return [](auto&& fplus_fwd_x) \
15421     { \
15422         return fplus::fplus_fwd_define_fn_0_name(std::forward<decltype(fplus_fwd_x)>(fplus_fwd_x)); \
15423     }; \
15424 }
15425 
15426 #define fplus_fwd_define_fn_1(fplus_fwd_define_fn_1_name) \
15427 template <typename P1> \
15428 auto fplus_fwd_define_fn_1_name(P1 p1) \
15429 { \
15430     return [p1](auto&& fplus_fwd_x) \
15431     { \
15432         return fplus::fplus_fwd_define_fn_1_name(p1, std::forward<decltype(fplus_fwd_x)>(fplus_fwd_x)); \
15433     }; \
15434 }
15435 
15436 #define fplus_fwd_define_fn_2(fplus_fwd_define_fn_2_name) \
15437 template <typename P1, typename P2> \
15438 auto fplus_fwd_define_fn_2_name(P1 p1, P2 p2) \
15439 { \
15440     return [p1, p2](auto&& fplus_fwd_x) \
15441     { \
15442         return fplus::fplus_fwd_define_fn_2_name(p1, p2, std::forward<decltype(fplus_fwd_x)>(fplus_fwd_x)); \
15443     }; \
15444 }
15445 
15446 #define fplus_fwd_define_fn_3(fplus_fwd_define_fn_3_name) \
15447 template <typename P1, typename P2, typename P3> \
15448 auto fplus_fwd_define_fn_3_name(P1 p1, P2 p2, P3 p3) \
15449 { \
15450     return [p1, p2, p3](auto&& fplus_fwd_x) \
15451     { \
15452         return fplus::fplus_fwd_define_fn_3_name(p1, p2, p3, std::forward<decltype(fplus_fwd_x)>(fplus_fwd_x)); \
15453     }; \
15454 }
15455 
15456 #define fplus_fwd_define_fn_4(fplus_fwd_define_fn_4_name) \
15457 template <typename P1, typename P2, typename P3, typename P4> \
15458 auto fplus_fwd_define_fn_4_name(P1 p1, P2 p2, P3 p3, P4 p4) \
15459 { \
15460     return [p1, p2, p3, p4](auto&& fplus_fwd_x) \
15461     { \
15462         return fplus::fplus_fwd_define_fn_4_name(p1, p2, p3, p4, std::forward<decltype(fplus_fwd_x)>(fplus_fwd_x)); \
15463     }; \
15464 }
15465 
15466 
15467 #define fplus_fwd_flip_define_fn_1(fplus_fwd_flip_define_fn_1_name) \
15468 namespace flip \
15469 { \
15470     template <typename P2> \
15471     auto fplus_fwd_flip_define_fn_1_name(P2 p2) \
15472     { \
15473         return [p2](auto&& fplus_fwd_flip_x) \
15474         { \
15475             return fplus::fplus_fwd_flip_define_fn_1_name(std::forward<decltype(fplus_fwd_flip_x)>(fplus_fwd_flip_x), p2); \
15476         }; \
15477     } \
15478 } // namespace flip
15479 
15480 
15481 namespace internal
15482 {
15483     template<typename F, typename G>
15484     struct compose_helper{
compose_helperfplus::fwd::internal::compose_helper15485         compose_helper(F f, G g) : f_(f), g_(g) {}
15486         template<typename X>
operator ()fplus::fwd::internal::compose_helper15487         decltype(auto) operator()(X&& x) const
15488         {
15489             return g_(f_(std::forward<X>(x)));
15490         }
15491     private:
15492         F f_;
15493         G g_;
15494     };
15495 } // namespace internal
15496 template<typename F, typename G>
compose(F f,G g)15497 auto compose(F f, G g) {
15498     return internal::compose_helper<F, G> {f, g};
15499 }
15500 template<typename F1, typename... Fs>
compose(F1 f,Fs...args)15501 auto compose(F1 f, Fs ... args)
15502 {
15503     return compose(f, compose(args...));
15504 }
15505 
15506 template<typename X, typename... Fs>
apply(X && x,Fs...args)15507 auto apply(X&& x, Fs ... args)
15508 {
15509     return compose(args...)(std::forward<X>(x));
15510 }
15511 template<typename X, typename F>
apply(X && x,F f)15512 auto apply(X&& x, F f)
15513 {
15514     return f(std::forward<X>(x));
15515 }
15516 
15517 
15518 //
15519 // fwd_instances.autogenerated_defines
15520 //
15521 
15522 // THIS FILE WAS GENERATED AUTOMATICALLY. DO NOT EDIT.
15523 fplus_fwd_define_fn_0(identity)
15524 fplus_fwd_define_fn_1(is_equal)
15525 fplus_fwd_define_fn_1(is_not_equal)
15526 fplus_fwd_define_fn_1(is_less)
15527 fplus_fwd_define_fn_1(is_less_or_equal)
15528 fplus_fwd_define_fn_1(is_greater)
15529 fplus_fwd_define_fn_1(is_greater_or_equal)
15530 fplus_fwd_define_fn_1(xor_bools)
15531 fplus_fwd_define_fn_0(is_just)
15532 fplus_fwd_define_fn_0(is_nothing)
15533 fplus_fwd_define_fn_0(unsafe_get_just)
15534 fplus_fwd_define_fn_0(just_with_default)
15535 fplus_fwd_define_fn_1(throw_on_nothing)
15536 fplus_fwd_define_fn_0(just)
15537 fplus_fwd_define_fn_1(as_just_if)
15538 fplus_fwd_define_fn_0(maybe_to_seq)
15539 fplus_fwd_define_fn_0(singleton_seq_as_maybe)
15540 fplus_fwd_define_fn_1(lift_maybe)
15541 fplus_fwd_define_fn_2(lift_maybe_def)
15542 fplus_fwd_define_fn_2(lift_maybe_2)
15543 fplus_fwd_define_fn_3(lift_maybe_2_def)
15544 fplus_fwd_define_fn_1(and_then_maybe)
15545 fplus_fwd_define_fn_0(flatten_maybe)
15546 fplus_fwd_define_fn_0(is_even)
15547 fplus_fwd_define_fn_0(is_odd)
15548 fplus_fwd_define_fn_0(is_empty)
15549 fplus_fwd_define_fn_0(is_not_empty)
15550 fplus_fwd_define_fn_0(size_of_cont)
15551 fplus_fwd_define_fn_0(convert)
15552 fplus_fwd_define_fn_0(convert_elems)
15553 fplus_fwd_define_fn_0(convert_container)
15554 fplus_fwd_define_fn_0(convert_container_and_elems)
15555 fplus_fwd_define_fn_2(get_segment)
15556 fplus_fwd_define_fn_2(set_segment)
15557 fplus_fwd_define_fn_2(remove_segment)
15558 fplus_fwd_define_fn_2(insert_at)
15559 fplus_fwd_define_fn_1(elem_at_idx)
15560 fplus_fwd_define_fn_1(elem_at_idx_maybe)
15561 fplus_fwd_define_fn_1(elems_at_idxs)
15562 fplus_fwd_define_fn_1(transform)
15563 fplus_fwd_define_fn_1(transform_convert)
15564 fplus_fwd_define_fn_1(transform_inner)
15565 fplus_fwd_define_fn_0(reverse)
15566 fplus_fwd_define_fn_1(take)
15567 fplus_fwd_define_fn_1(take_exact)
15568 fplus_fwd_define_fn_1(take_cyclic)
15569 fplus_fwd_define_fn_1(drop)
15570 fplus_fwd_define_fn_1(take_last)
15571 fplus_fwd_define_fn_1(drop_last)
15572 fplus_fwd_define_fn_1(drop_exact)
15573 fplus_fwd_define_fn_1(take_while)
15574 fplus_fwd_define_fn_1(take_last_while)
15575 fplus_fwd_define_fn_1(drop_while)
15576 fplus_fwd_define_fn_1(drop_last_while)
15577 fplus_fwd_define_fn_2(fold_left)
15578 fplus_fwd_define_fn_2(reduce)
15579 fplus_fwd_define_fn_1(fold_left_1)
15580 fplus_fwd_define_fn_1(reduce_1)
15581 fplus_fwd_define_fn_2(fold_right)
15582 fplus_fwd_define_fn_1(fold_right_1)
15583 fplus_fwd_define_fn_2(scan_left)
15584 fplus_fwd_define_fn_1(scan_left_1)
15585 fplus_fwd_define_fn_2(scan_right)
15586 fplus_fwd_define_fn_1(scan_right_1)
15587 fplus_fwd_define_fn_0(sum)
15588 fplus_fwd_define_fn_0(product)
15589 fplus_fwd_define_fn_1(append_elem)
15590 fplus_fwd_define_fn_1(prepend_elem)
15591 fplus_fwd_define_fn_1(append)
15592 fplus_fwd_define_fn_1(append_convert)
15593 fplus_fwd_define_fn_0(concat)
15594 fplus_fwd_define_fn_1(interweave)
15595 fplus_fwd_define_fn_0(unweave)
15596 fplus_fwd_define_fn_1(sort_by)
15597 fplus_fwd_define_fn_1(sort_on)
15598 fplus_fwd_define_fn_0(sort)
15599 fplus_fwd_define_fn_1(stable_sort_by)
15600 fplus_fwd_define_fn_1(stable_sort_on)
15601 fplus_fwd_define_fn_0(stable_sort)
15602 fplus_fwd_define_fn_2(partial_sort_by)
15603 fplus_fwd_define_fn_2(partial_sort_on)
15604 fplus_fwd_define_fn_1(partial_sort)
15605 fplus_fwd_define_fn_2(nth_element_by)
15606 fplus_fwd_define_fn_2(nth_element_on)
15607 fplus_fwd_define_fn_1(nth_element)
15608 fplus_fwd_define_fn_1(unique_by)
15609 fplus_fwd_define_fn_1(unique_on)
15610 fplus_fwd_define_fn_0(unique)
15611 fplus_fwd_define_fn_1(intersperse)
15612 fplus_fwd_define_fn_1(join)
15613 fplus_fwd_define_fn_1(join_elem)
15614 fplus_fwd_define_fn_1(is_elem_of_by)
15615 fplus_fwd_define_fn_1(is_elem_of)
15616 fplus_fwd_define_fn_1(nub_by)
15617 fplus_fwd_define_fn_1(nub_on)
15618 fplus_fwd_define_fn_0(nub)
15619 fplus_fwd_define_fn_1(all_unique_by_eq)
15620 fplus_fwd_define_fn_1(all_unique_on)
15621 fplus_fwd_define_fn_0(all_unique)
15622 fplus_fwd_define_fn_1(is_strictly_sorted_by)
15623 fplus_fwd_define_fn_1(is_strictly_sorted_on)
15624 fplus_fwd_define_fn_0(is_strictly_sorted)
15625 fplus_fwd_define_fn_1(is_sorted_by)
15626 fplus_fwd_define_fn_1(is_sorted_on)
15627 fplus_fwd_define_fn_0(is_sorted)
15628 fplus_fwd_define_fn_1(is_prefix_of)
15629 fplus_fwd_define_fn_1(is_suffix_of)
15630 fplus_fwd_define_fn_1(all_by)
15631 fplus_fwd_define_fn_0(all)
15632 fplus_fwd_define_fn_1(all_the_same_by)
15633 fplus_fwd_define_fn_1(all_the_same_on)
15634 fplus_fwd_define_fn_0(all_the_same)
15635 fplus_fwd_define_fn_2(numbers_step)
15636 fplus_fwd_define_fn_1(numbers)
15637 fplus_fwd_define_fn_0(singleton_seq)
15638 fplus_fwd_define_fn_0(all_idxs)
15639 fplus_fwd_define_fn_0(init)
15640 fplus_fwd_define_fn_0(tail)
15641 fplus_fwd_define_fn_0(head)
15642 fplus_fwd_define_fn_0(last)
15643 fplus_fwd_define_fn_0(mean_stddev)
15644 fplus_fwd_define_fn_1(count_occurrences_by)
15645 fplus_fwd_define_fn_0(count_occurrences)
15646 fplus_fwd_define_fn_2(lexicographical_less_by)
15647 fplus_fwd_define_fn_1(lexicographical_less)
15648 fplus_fwd_define_fn_0(lexicographical_sort)
15649 fplus_fwd_define_fn_1(replicate)
15650 fplus_fwd_define_fn_2(instead_of_if)
15651 fplus_fwd_define_fn_2(instead_of_if_empty)
15652 fplus_fwd_define_fn_0(is_ok)
15653 fplus_fwd_define_fn_0(is_error)
15654 fplus_fwd_define_fn_0(unsafe_get_ok)
15655 fplus_fwd_define_fn_0(unsafe_get_error)
15656 fplus_fwd_define_fn_1(ok_with_default)
15657 fplus_fwd_define_fn_0(ok)
15658 fplus_fwd_define_fn_0(error)
15659 fplus_fwd_define_fn_0(to_maybe)
15660 fplus_fwd_define_fn_1(from_maybe)
15661 fplus_fwd_define_fn_1(throw_on_error)
15662 fplus_fwd_define_fn_1(lift_result)
15663 fplus_fwd_define_fn_2(lift_result_both)
15664 fplus_fwd_define_fn_2(unify_result)
15665 fplus_fwd_define_fn_1(and_then_result)
15666 fplus_fwd_define_fn_1(keep_if)
15667 fplus_fwd_define_fn_1(drop_if)
15668 fplus_fwd_define_fn_1(without)
15669 fplus_fwd_define_fn_1(without_any)
15670 fplus_fwd_define_fn_1(keep_if_with_idx)
15671 fplus_fwd_define_fn_1(drop_if_with_idx)
15672 fplus_fwd_define_fn_1(keep_by_idx)
15673 fplus_fwd_define_fn_1(drop_by_idx)
15674 fplus_fwd_define_fn_1(keep_idxs)
15675 fplus_fwd_define_fn_1(drop_idxs)
15676 fplus_fwd_define_fn_1(drop_idx)
15677 fplus_fwd_define_fn_0(justs)
15678 fplus_fwd_define_fn_0(oks)
15679 fplus_fwd_define_fn_0(errors)
15680 fplus_fwd_define_fn_1(trim_left)
15681 fplus_fwd_define_fn_1(trim_token_left)
15682 fplus_fwd_define_fn_1(trim_right_by)
15683 fplus_fwd_define_fn_1(trim_right)
15684 fplus_fwd_define_fn_1(trim_token_right)
15685 fplus_fwd_define_fn_1(trim_by)
15686 fplus_fwd_define_fn_1(trim)
15687 fplus_fwd_define_fn_1(trim_token)
15688 fplus_fwd_define_fn_1(adjacent_keep_snd_if)
15689 fplus_fwd_define_fn_1(adjacent_drop_fst_if)
15690 fplus_fwd_define_fn_1(adjacent_drop_snd_if)
15691 fplus_fwd_define_fn_1(adjacent_keep_fst_if)
15692 fplus_fwd_define_fn_1(generate_by_idx)
15693 fplus_fwd_define_fn_1(repeat)
15694 fplus_fwd_define_fn_1(infixes)
15695 fplus_fwd_define_fn_3(carthesian_product_with_where)
15696 fplus_fwd_define_fn_2(carthesian_product_with)
15697 fplus_fwd_define_fn_2(carthesian_product_where)
15698 fplus_fwd_define_fn_1(carthesian_product)
15699 fplus_fwd_define_fn_1(carthesian_product_n)
15700 fplus_fwd_define_fn_1(permutations)
15701 fplus_fwd_define_fn_1(combinations)
15702 fplus_fwd_define_fn_1(combinations_with_replacement)
15703 fplus_fwd_define_fn_0(power_set)
15704 fplus_fwd_define_fn_2(iterate)
15705 fplus_fwd_define_fn_1(iterate_maybe)
15706 fplus_fwd_define_fn_1(adjacent_difference_by)
15707 fplus_fwd_define_fn_0(adjacent_difference)
15708 fplus_fwd_define_fn_0(rotate_left)
15709 fplus_fwd_define_fn_0(rotate_right)
15710 fplus_fwd_define_fn_0(rotations_left)
15711 fplus_fwd_define_fn_0(rotations_right)
15712 fplus_fwd_define_fn_2(fill_left)
15713 fplus_fwd_define_fn_2(fill_right)
15714 fplus_fwd_define_fn_0(inits)
15715 fplus_fwd_define_fn_0(tails)
15716 fplus_fwd_define_fn_1(apply_to_pair)
15717 fplus_fwd_define_fn_2(zip_with)
15718 fplus_fwd_define_fn_3(zip_with_3)
15719 fplus_fwd_define_fn_4(zip_with_defaults)
15720 fplus_fwd_define_fn_1(zip)
15721 fplus_fwd_define_fn_1(zip_repeat)
15722 fplus_fwd_define_fn_0(unzip)
15723 fplus_fwd_define_fn_0(fst)
15724 fplus_fwd_define_fn_0(snd)
15725 fplus_fwd_define_fn_1(transform_fst)
15726 fplus_fwd_define_fn_1(transform_snd)
15727 fplus_fwd_define_fn_2(transform_pair)
15728 fplus_fwd_define_fn_0(swap_pair_elems)
15729 fplus_fwd_define_fn_0(swap_pairs_elems)
15730 fplus_fwd_define_fn_0(adjacent_pairs)
15731 fplus_fwd_define_fn_0(overlapping_pairs)
15732 fplus_fwd_define_fn_0(overlapping_pairs_cyclic)
15733 fplus_fwd_define_fn_0(enumerate)
15734 fplus_fwd_define_fn_4(inner_product_with)
15735 fplus_fwd_define_fn_2(inner_product)
15736 fplus_fwd_define_fn_2(first_mismatch_idx_by)
15737 fplus_fwd_define_fn_2(first_mismatch_by)
15738 fplus_fwd_define_fn_2(first_mismatch_idx_on)
15739 fplus_fwd_define_fn_2(first_mismatch_on)
15740 fplus_fwd_define_fn_2(first_mismatch_idx)
15741 fplus_fwd_define_fn_2(first_mismatch)
15742 fplus_fwd_define_fn_2(first_match_idx_by)
15743 fplus_fwd_define_fn_2(first_match_by)
15744 fplus_fwd_define_fn_2(first_match_idx_on)
15745 fplus_fwd_define_fn_2(first_match_on)
15746 fplus_fwd_define_fn_2(first_match_idx)
15747 fplus_fwd_define_fn_2(first_match)
15748 fplus_fwd_define_fn_2(is_in_interval)
15749 fplus_fwd_define_fn_2(is_in_interval_around)
15750 fplus_fwd_define_fn_2(is_in_open_interval)
15751 fplus_fwd_define_fn_2(is_in_open_interval_around)
15752 fplus_fwd_define_fn_2(is_in_closed_interval)
15753 fplus_fwd_define_fn_4(reference_interval)
15754 fplus_fwd_define_fn_2(clamp)
15755 fplus_fwd_define_fn_0(is_negative)
15756 fplus_fwd_define_fn_0(is_positive)
15757 fplus_fwd_define_fn_0(abs)
15758 fplus_fwd_define_fn_1(abs_diff)
15759 fplus_fwd_define_fn_0(square)
15760 fplus_fwd_define_fn_0(cube)
15761 fplus_fwd_define_fn_0(sign)
15762 fplus_fwd_define_fn_0(sign_with_zero)
15763 fplus_fwd_define_fn_0(integral_cast_throw)
15764 fplus_fwd_define_fn_0(integral_cast_clamp)
15765 fplus_fwd_define_fn_0(round)
15766 fplus_fwd_define_fn_0(floor)
15767 fplus_fwd_define_fn_1(floor_to_int_mult)
15768 fplus_fwd_define_fn_1(ceil_to_int_mult)
15769 fplus_fwd_define_fn_0(ceil)
15770 fplus_fwd_define_fn_1(int_power)
15771 fplus_fwd_define_fn_2(min_2_on)
15772 fplus_fwd_define_fn_2(max_2_on)
15773 fplus_fwd_define_fn_1(min_2)
15774 fplus_fwd_define_fn_1(max_2)
15775 fplus_fwd_define_fn_0(deg_to_rad)
15776 fplus_fwd_define_fn_0(rad_to_deg)
15777 fplus_fwd_define_fn_2(normalize_min_max)
15778 fplus_fwd_define_fn_2(normalize_mean_stddev)
15779 fplus_fwd_define_fn_0(standardize)
15780 fplus_fwd_define_fn_1(histogram_using_intervals)
15781 fplus_fwd_define_fn_2(generate_consecutive_intervals)
15782 fplus_fwd_define_fn_3(histogram)
15783 fplus_fwd_define_fn_1(modulo_chain)
15784 fplus_fwd_define_fn_2(line_equation)
15785 fplus_fwd_define_fn_1(find_first_by)
15786 fplus_fwd_define_fn_1(find_last_by)
15787 fplus_fwd_define_fn_1(find_first_idx_by)
15788 fplus_fwd_define_fn_1(find_last_idx_by)
15789 fplus_fwd_define_fn_1(find_first_idx)
15790 fplus_fwd_define_fn_1(find_last_idx)
15791 fplus_fwd_define_fn_1(find_all_idxs_by)
15792 fplus_fwd_define_fn_1(find_all_idxs_of)
15793 fplus_fwd_define_fn_1(find_all_instances_of_token)
15794 fplus_fwd_define_fn_1(find_all_instances_of_token_non_overlapping)
15795 fplus_fwd_define_fn_1(find_first_instance_of_token)
15796 fplus_fwd_define_fn_1(set_includes)
15797 fplus_fwd_define_fn_1(unordered_set_includes)
15798 fplus_fwd_define_fn_1(set_merge)
15799 fplus_fwd_define_fn_1(unordered_set_merge)
15800 fplus_fwd_define_fn_1(set_intersection)
15801 fplus_fwd_define_fn_1(unordered_set_intersection)
15802 fplus_fwd_define_fn_1(set_is_disjoint)
15803 fplus_fwd_define_fn_1(unordered_set_is_disjoint)
15804 fplus_fwd_define_fn_1(set_difference)
15805 fplus_fwd_define_fn_1(unordered_set_difference)
15806 fplus_fwd_define_fn_1(set_symmetric_difference)
15807 fplus_fwd_define_fn_1(unordered_set_symmetric_difference)
15808 fplus_fwd_define_fn_0(sets_intersection)
15809 fplus_fwd_define_fn_0(unordered_sets_intersection)
15810 fplus_fwd_define_fn_1(any_by)
15811 fplus_fwd_define_fn_0(any)
15812 fplus_fwd_define_fn_1(none_by)
15813 fplus_fwd_define_fn_0(none)
15814 fplus_fwd_define_fn_1(minimum_idx_by)
15815 fplus_fwd_define_fn_1(minimum_idx_by_maybe)
15816 fplus_fwd_define_fn_1(maximum_idx_by)
15817 fplus_fwd_define_fn_1(maximum_idx_by_maybe)
15818 fplus_fwd_define_fn_0(minimum_idx)
15819 fplus_fwd_define_fn_0(minimum_idx_maybe)
15820 fplus_fwd_define_fn_0(maximum_idx)
15821 fplus_fwd_define_fn_0(maximum_idx_maybe)
15822 fplus_fwd_define_fn_1(minimum_idx_on)
15823 fplus_fwd_define_fn_1(minimum_idx_on_maybe)
15824 fplus_fwd_define_fn_1(maximum_idx_on)
15825 fplus_fwd_define_fn_1(maximum_idx_on_maybe)
15826 fplus_fwd_define_fn_1(minimum_by)
15827 fplus_fwd_define_fn_1(minimum_by_maybe)
15828 fplus_fwd_define_fn_1(maximum_by)
15829 fplus_fwd_define_fn_1(maximum_by_maybe)
15830 fplus_fwd_define_fn_0(minimum)
15831 fplus_fwd_define_fn_0(minimum_maybe)
15832 fplus_fwd_define_fn_0(maximum)
15833 fplus_fwd_define_fn_0(maximum_maybe)
15834 fplus_fwd_define_fn_1(minimum_on)
15835 fplus_fwd_define_fn_1(minimum_on_maybe)
15836 fplus_fwd_define_fn_1(maximum_on)
15837 fplus_fwd_define_fn_1(maximum_on_maybe)
15838 fplus_fwd_define_fn_0(mean)
15839 fplus_fwd_define_fn_0(mean_obj_div_size_t)
15840 fplus_fwd_define_fn_0(mean_obj_div_double)
15841 fplus_fwd_define_fn_0(mean_using_doubles)
15842 fplus_fwd_define_fn_0(median)
15843 fplus_fwd_define_fn_1(all_unique_by_less)
15844 fplus_fwd_define_fn_0(all_unique_less)
15845 fplus_fwd_define_fn_1(is_infix_of)
15846 fplus_fwd_define_fn_1(is_subsequence_of)
15847 fplus_fwd_define_fn_1(count_if)
15848 fplus_fwd_define_fn_1(count)
15849 fplus_fwd_define_fn_1(is_unique_in_by)
15850 fplus_fwd_define_fn_1(is_unique_in)
15851 fplus_fwd_define_fn_1(is_permutation_of)
15852 fplus_fwd_define_fn_1(fill_pigeonholes_to)
15853 fplus_fwd_define_fn_0(fill_pigeonholes)
15854 fplus_fwd_define_fn_1(fill_pigeonholes_bool_to)
15855 fplus_fwd_define_fn_0(fill_pigeonholes_bool)
15856 fplus_fwd_define_fn_0(present_in_all)
15857 fplus_fwd_define_fn_1(elem_at_idx_or_nothing)
15858 fplus_fwd_define_fn_2(elem_at_idx_or_constant)
15859 fplus_fwd_define_fn_1(elem_at_idx_or_replicate)
15860 fplus_fwd_define_fn_1(elem_at_idx_or_wrap)
15861 fplus_fwd_define_fn_2(extrapolate_replicate)
15862 fplus_fwd_define_fn_2(extrapolate_wrap)
15863 fplus_fwd_define_fn_1(elem_at_float_idx)
15864 fplus_fwd_define_fn_0(pairs_to_map)
15865 fplus_fwd_define_fn_0(pairs_to_map_grouped)
15866 fplus_fwd_define_fn_0(pairs_to_unordered_map_grouped)
15867 fplus_fwd_define_fn_0(map_to_pairs)
15868 fplus_fwd_define_fn_1(transform_map_values)
15869 fplus_fwd_define_fn_2(map_union_with)
15870 fplus_fwd_define_fn_1(map_union)
15871 fplus_fwd_define_fn_0(map_grouped_to_pairs)
15872 fplus_fwd_define_fn_0(get_map_keys)
15873 fplus_fwd_define_fn_0(get_map_values)
15874 fplus_fwd_define_fn_0(swap_keys_and_values)
15875 fplus_fwd_define_fn_1(create_map)
15876 fplus_fwd_define_fn_1(create_map_with)
15877 fplus_fwd_define_fn_1(create_map_grouped)
15878 fplus_fwd_define_fn_1(create_unordered_map)
15879 fplus_fwd_define_fn_1(create_unordered_map_with)
15880 fplus_fwd_define_fn_1(create_unordered_map_grouped)
15881 fplus_fwd_define_fn_1(get_from_map)
15882 fplus_fwd_define_fn_1(get_from_map_unsafe)
15883 fplus_fwd_define_fn_2(get_from_map_with_def)
15884 fplus_fwd_define_fn_1(get_first_from_map)
15885 fplus_fwd_define_fn_1(get_first_from_map_unsafe)
15886 fplus_fwd_define_fn_2(get_first_from_map_with_def)
15887 fplus_fwd_define_fn_1(map_contains)
15888 fplus_fwd_define_fn_1(map_keep_if)
15889 fplus_fwd_define_fn_1(map_drop_if)
15890 fplus_fwd_define_fn_1(map_keep)
15891 fplus_fwd_define_fn_1(map_drop)
15892 fplus_fwd_define_fn_1(map_keep_if_value)
15893 fplus_fwd_define_fn_1(map_drop_if_value)
15894 fplus_fwd_define_fn_1(map_keep_values)
15895 fplus_fwd_define_fn_1(map_drop_values)
15896 fplus_fwd_define_fn_1(map_pluck)
15897 fplus_fwd_define_fn_1(choose)
15898 fplus_fwd_define_fn_2(choose_by)
15899 fplus_fwd_define_fn_1(choose_lazy)
15900 fplus_fwd_define_fn_2(choose_by_lazy)
15901 fplus_fwd_define_fn_1(choose_def)
15902 fplus_fwd_define_fn_2(choose_by_def)
15903 fplus_fwd_define_fn_1(choose_def_lazy)
15904 fplus_fwd_define_fn_2(choose_by_def_lazy)
15905 fplus_fwd_define_fn_1(group_by)
15906 fplus_fwd_define_fn_1(group_on)
15907 fplus_fwd_define_fn_1(group_on_labeled)
15908 fplus_fwd_define_fn_0(group)
15909 fplus_fwd_define_fn_1(group_globally_by)
15910 fplus_fwd_define_fn_1(group_globally_on)
15911 fplus_fwd_define_fn_1(group_globally_on_labeled)
15912 fplus_fwd_define_fn_0(group_globally)
15913 fplus_fwd_define_fn_1(cluster_by)
15914 fplus_fwd_define_fn_2(split_by)
15915 fplus_fwd_define_fn_1(split_by_keep_separators)
15916 fplus_fwd_define_fn_2(split)
15917 fplus_fwd_define_fn_2(split_one_of)
15918 fplus_fwd_define_fn_1(split_keep_separators)
15919 fplus_fwd_define_fn_1(split_at_idx)
15920 fplus_fwd_define_fn_2(insert_at_idx)
15921 fplus_fwd_define_fn_1(partition)
15922 fplus_fwd_define_fn_1(split_at_idxs)
15923 fplus_fwd_define_fn_1(split_every)
15924 fplus_fwd_define_fn_2(split_by_token)
15925 fplus_fwd_define_fn_1(run_length_encode_by)
15926 fplus_fwd_define_fn_0(run_length_encode)
15927 fplus_fwd_define_fn_0(run_length_decode)
15928 fplus_fwd_define_fn_1(span)
15929 fplus_fwd_define_fn_2(divvy)
15930 fplus_fwd_define_fn_1(aperture)
15931 fplus_fwd_define_fn_1(stride)
15932 fplus_fwd_define_fn_1(winsorize)
15933 fplus_fwd_define_fn_1(separate_on)
15934 fplus_fwd_define_fn_0(separate)
15935 fplus_fwd_define_fn_1(transform_with_idx)
15936 fplus_fwd_define_fn_1(transform_and_keep_justs)
15937 fplus_fwd_define_fn_1(transform_and_keep_oks)
15938 fplus_fwd_define_fn_1(transform_and_concat)
15939 fplus_fwd_define_fn_1(replicate_elems)
15940 fplus_fwd_define_fn_0(interleave)
15941 fplus_fwd_define_fn_0(transpose)
15942 fplus_fwd_define_fn_1(shuffle)
15943 fplus_fwd_define_fn_2(sample)
15944 fplus_fwd_define_fn_1(random_element)
15945 fplus_fwd_define_fn_2(random_elements)
15946 fplus_fwd_define_fn_1(apply_functions)
15947 fplus_fwd_define_fn_2(apply_function_n_times)
15948 fplus_fwd_define_fn_1(transform_parallelly)
15949 fplus_fwd_define_fn_2(transform_parallelly_n_threads)
15950 fplus_fwd_define_fn_2(reduce_parallelly)
15951 fplus_fwd_define_fn_3(reduce_parallelly_n_threads)
15952 fplus_fwd_define_fn_1(reduce_1_parallelly)
15953 fplus_fwd_define_fn_2(reduce_1_parallelly_n_threads)
15954 fplus_fwd_define_fn_1(keep_if_parallelly)
15955 fplus_fwd_define_fn_2(keep_if_parallelly_n_threads)
15956 fplus_fwd_define_fn_3(transform_reduce)
15957 fplus_fwd_define_fn_2(transform_reduce_1)
15958 fplus_fwd_define_fn_3(transform_reduce_parallelly)
15959 fplus_fwd_define_fn_4(transform_reduce_parallelly_n_threads)
15960 fplus_fwd_define_fn_2(transform_reduce_1_parallelly)
15961 fplus_fwd_define_fn_3(transform_reduce_1_parallelly_n_threads)
15962 fplus_fwd_define_fn_1(read_value_with_default)
15963 fplus_fwd_define_fn_2(replace_if)
15964 fplus_fwd_define_fn_2(replace_elem_at_idx)
15965 fplus_fwd_define_fn_2(replace_elems)
15966 fplus_fwd_define_fn_2(replace_tokens)
15967 fplus_fwd_define_fn_0(show)
15968 fplus_fwd_define_fn_3(show_cont_with_frame_and_newlines)
15969 fplus_fwd_define_fn_3(show_cont_with_frame)
15970 fplus_fwd_define_fn_1(show_cont_with)
15971 fplus_fwd_define_fn_0(show_cont)
15972 fplus_fwd_define_fn_0(show_maybe)
15973 fplus_fwd_define_fn_0(show_result)
15974 fplus_fwd_define_fn_2(show_float)
15975 fplus_fwd_define_fn_3(show_float_fill_left)
15976 fplus_fwd_define_fn_2(show_fill_left)
15977 fplus_fwd_define_fn_2(show_fill_right)
15978 fplus_fwd_define_fn_0(is_letter_or_digit)
15979 fplus_fwd_define_fn_0(is_whitespace)
15980 fplus_fwd_define_fn_0(is_line_break)
15981 fplus_fwd_define_fn_0(clean_newlines)
15982 fplus_fwd_define_fn_1(split_words)
15983 fplus_fwd_define_fn_1(split_lines)
15984 fplus_fwd_define_fn_0(trim_whitespace_left)
15985 fplus_fwd_define_fn_0(trim_whitespace_right)
15986 fplus_fwd_define_fn_0(trim_whitespace)
15987 fplus_fwd_define_fn_0(to_lower_case)
15988 fplus_fwd_define_fn_1(to_lower_case_loc)
15989 fplus_fwd_define_fn_0(to_upper_case)
15990 fplus_fwd_define_fn_1(to_upper_case_loc)
15991 fplus_fwd_define_fn_2(to_string_fill_left)
15992 fplus_fwd_define_fn_2(to_string_fill_right)
15993 fplus_fwd_define_fn_1(trees_from_sequence)
15994 fplus_fwd_define_fn_1(are_trees_equal)
15995 fplus_fwd_define_fn_0(tree_size)
15996 fplus_fwd_define_fn_0(tree_depth)
15997 fplus_fwd_define_fn_0(flatten_tree_depth_first)
15998 fplus_fwd_define_fn_0(flatten_tree_breadth_first)
15999 fplus_fwd_define_fn_0(show_timed)
16000 fplus_fwd_define_fn_0(make_timed_function)
16001 fplus_fwd_define_fn_0(make_timed_void_function)
16002 fplus_fwd_flip_define_fn_1(is_equal)
16003 fplus_fwd_flip_define_fn_1(is_not_equal)
16004 fplus_fwd_flip_define_fn_1(is_less)
16005 fplus_fwd_flip_define_fn_1(is_less_or_equal)
16006 fplus_fwd_flip_define_fn_1(is_greater)
16007 fplus_fwd_flip_define_fn_1(is_greater_or_equal)
16008 fplus_fwd_flip_define_fn_1(xor_bools)
16009 fplus_fwd_flip_define_fn_1(throw_on_nothing)
16010 fplus_fwd_flip_define_fn_1(as_just_if)
16011 fplus_fwd_flip_define_fn_1(lift_maybe)
16012 fplus_fwd_flip_define_fn_1(and_then_maybe)
16013 fplus_fwd_flip_define_fn_1(elem_at_idx)
16014 fplus_fwd_flip_define_fn_1(elem_at_idx_maybe)
16015 fplus_fwd_flip_define_fn_1(elems_at_idxs)
16016 fplus_fwd_flip_define_fn_1(transform)
16017 fplus_fwd_flip_define_fn_1(transform_convert)
16018 fplus_fwd_flip_define_fn_1(transform_inner)
16019 fplus_fwd_flip_define_fn_1(take)
16020 fplus_fwd_flip_define_fn_1(take_exact)
16021 fplus_fwd_flip_define_fn_1(take_cyclic)
16022 fplus_fwd_flip_define_fn_1(drop)
16023 fplus_fwd_flip_define_fn_1(take_last)
16024 fplus_fwd_flip_define_fn_1(drop_last)
16025 fplus_fwd_flip_define_fn_1(drop_exact)
16026 fplus_fwd_flip_define_fn_1(take_while)
16027 fplus_fwd_flip_define_fn_1(take_last_while)
16028 fplus_fwd_flip_define_fn_1(drop_while)
16029 fplus_fwd_flip_define_fn_1(drop_last_while)
16030 fplus_fwd_flip_define_fn_1(fold_left_1)
16031 fplus_fwd_flip_define_fn_1(reduce_1)
16032 fplus_fwd_flip_define_fn_1(fold_right_1)
16033 fplus_fwd_flip_define_fn_1(scan_left_1)
16034 fplus_fwd_flip_define_fn_1(scan_right_1)
16035 fplus_fwd_flip_define_fn_1(append_elem)
16036 fplus_fwd_flip_define_fn_1(prepend_elem)
16037 fplus_fwd_flip_define_fn_1(append)
16038 fplus_fwd_flip_define_fn_1(append_convert)
16039 fplus_fwd_flip_define_fn_1(interweave)
16040 fplus_fwd_flip_define_fn_1(sort_by)
16041 fplus_fwd_flip_define_fn_1(sort_on)
16042 fplus_fwd_flip_define_fn_1(stable_sort_by)
16043 fplus_fwd_flip_define_fn_1(stable_sort_on)
16044 fplus_fwd_flip_define_fn_1(partial_sort)
16045 fplus_fwd_flip_define_fn_1(nth_element)
16046 fplus_fwd_flip_define_fn_1(unique_by)
16047 fplus_fwd_flip_define_fn_1(unique_on)
16048 fplus_fwd_flip_define_fn_1(intersperse)
16049 fplus_fwd_flip_define_fn_1(join)
16050 fplus_fwd_flip_define_fn_1(join_elem)
16051 fplus_fwd_flip_define_fn_1(is_elem_of_by)
16052 fplus_fwd_flip_define_fn_1(is_elem_of)
16053 fplus_fwd_flip_define_fn_1(nub_by)
16054 fplus_fwd_flip_define_fn_1(nub_on)
16055 fplus_fwd_flip_define_fn_1(all_unique_by_eq)
16056 fplus_fwd_flip_define_fn_1(all_unique_on)
16057 fplus_fwd_flip_define_fn_1(is_strictly_sorted_by)
16058 fplus_fwd_flip_define_fn_1(is_strictly_sorted_on)
16059 fplus_fwd_flip_define_fn_1(is_sorted_by)
16060 fplus_fwd_flip_define_fn_1(is_sorted_on)
16061 fplus_fwd_flip_define_fn_1(is_prefix_of)
16062 fplus_fwd_flip_define_fn_1(is_suffix_of)
16063 fplus_fwd_flip_define_fn_1(all_by)
16064 fplus_fwd_flip_define_fn_1(all_the_same_by)
16065 fplus_fwd_flip_define_fn_1(all_the_same_on)
16066 fplus_fwd_flip_define_fn_1(numbers)
16067 fplus_fwd_flip_define_fn_1(count_occurrences_by)
16068 fplus_fwd_flip_define_fn_1(lexicographical_less)
16069 fplus_fwd_flip_define_fn_1(replicate)
16070 fplus_fwd_flip_define_fn_1(ok_with_default)
16071 fplus_fwd_flip_define_fn_1(from_maybe)
16072 fplus_fwd_flip_define_fn_1(throw_on_error)
16073 fplus_fwd_flip_define_fn_1(lift_result)
16074 fplus_fwd_flip_define_fn_1(and_then_result)
16075 fplus_fwd_flip_define_fn_1(keep_if)
16076 fplus_fwd_flip_define_fn_1(drop_if)
16077 fplus_fwd_flip_define_fn_1(without)
16078 fplus_fwd_flip_define_fn_1(without_any)
16079 fplus_fwd_flip_define_fn_1(keep_if_with_idx)
16080 fplus_fwd_flip_define_fn_1(drop_if_with_idx)
16081 fplus_fwd_flip_define_fn_1(keep_by_idx)
16082 fplus_fwd_flip_define_fn_1(drop_by_idx)
16083 fplus_fwd_flip_define_fn_1(keep_idxs)
16084 fplus_fwd_flip_define_fn_1(drop_idxs)
16085 fplus_fwd_flip_define_fn_1(drop_idx)
16086 fplus_fwd_flip_define_fn_1(trim_left)
16087 fplus_fwd_flip_define_fn_1(trim_token_left)
16088 fplus_fwd_flip_define_fn_1(trim_right_by)
16089 fplus_fwd_flip_define_fn_1(trim_right)
16090 fplus_fwd_flip_define_fn_1(trim_token_right)
16091 fplus_fwd_flip_define_fn_1(trim_by)
16092 fplus_fwd_flip_define_fn_1(trim)
16093 fplus_fwd_flip_define_fn_1(trim_token)
16094 fplus_fwd_flip_define_fn_1(adjacent_keep_snd_if)
16095 fplus_fwd_flip_define_fn_1(adjacent_drop_fst_if)
16096 fplus_fwd_flip_define_fn_1(adjacent_drop_snd_if)
16097 fplus_fwd_flip_define_fn_1(adjacent_keep_fst_if)
16098 fplus_fwd_flip_define_fn_1(generate_by_idx)
16099 fplus_fwd_flip_define_fn_1(repeat)
16100 fplus_fwd_flip_define_fn_1(infixes)
16101 fplus_fwd_flip_define_fn_1(carthesian_product)
16102 fplus_fwd_flip_define_fn_1(carthesian_product_n)
16103 fplus_fwd_flip_define_fn_1(permutations)
16104 fplus_fwd_flip_define_fn_1(combinations)
16105 fplus_fwd_flip_define_fn_1(combinations_with_replacement)
16106 fplus_fwd_flip_define_fn_1(iterate_maybe)
16107 fplus_fwd_flip_define_fn_1(adjacent_difference_by)
16108 fplus_fwd_flip_define_fn_1(apply_to_pair)
16109 fplus_fwd_flip_define_fn_1(zip)
16110 fplus_fwd_flip_define_fn_1(zip_repeat)
16111 fplus_fwd_flip_define_fn_1(transform_fst)
16112 fplus_fwd_flip_define_fn_1(transform_snd)
16113 fplus_fwd_flip_define_fn_1(abs_diff)
16114 fplus_fwd_flip_define_fn_1(floor_to_int_mult)
16115 fplus_fwd_flip_define_fn_1(ceil_to_int_mult)
16116 fplus_fwd_flip_define_fn_1(int_power)
16117 fplus_fwd_flip_define_fn_1(min_2)
16118 fplus_fwd_flip_define_fn_1(max_2)
16119 fplus_fwd_flip_define_fn_1(histogram_using_intervals)
16120 fplus_fwd_flip_define_fn_1(modulo_chain)
16121 fplus_fwd_flip_define_fn_1(find_first_by)
16122 fplus_fwd_flip_define_fn_1(find_last_by)
16123 fplus_fwd_flip_define_fn_1(find_first_idx_by)
16124 fplus_fwd_flip_define_fn_1(find_last_idx_by)
16125 fplus_fwd_flip_define_fn_1(find_first_idx)
16126 fplus_fwd_flip_define_fn_1(find_last_idx)
16127 fplus_fwd_flip_define_fn_1(find_all_idxs_by)
16128 fplus_fwd_flip_define_fn_1(find_all_idxs_of)
16129 fplus_fwd_flip_define_fn_1(find_all_instances_of_token)
16130 fplus_fwd_flip_define_fn_1(find_all_instances_of_token_non_overlapping)
16131 fplus_fwd_flip_define_fn_1(find_first_instance_of_token)
16132 fplus_fwd_flip_define_fn_1(set_includes)
16133 fplus_fwd_flip_define_fn_1(unordered_set_includes)
16134 fplus_fwd_flip_define_fn_1(set_merge)
16135 fplus_fwd_flip_define_fn_1(unordered_set_merge)
16136 fplus_fwd_flip_define_fn_1(set_intersection)
16137 fplus_fwd_flip_define_fn_1(unordered_set_intersection)
16138 fplus_fwd_flip_define_fn_1(set_is_disjoint)
16139 fplus_fwd_flip_define_fn_1(unordered_set_is_disjoint)
16140 fplus_fwd_flip_define_fn_1(set_difference)
16141 fplus_fwd_flip_define_fn_1(unordered_set_difference)
16142 fplus_fwd_flip_define_fn_1(set_symmetric_difference)
16143 fplus_fwd_flip_define_fn_1(unordered_set_symmetric_difference)
16144 fplus_fwd_flip_define_fn_1(any_by)
16145 fplus_fwd_flip_define_fn_1(none_by)
16146 fplus_fwd_flip_define_fn_1(minimum_idx_by)
16147 fplus_fwd_flip_define_fn_1(minimum_idx_by_maybe)
16148 fplus_fwd_flip_define_fn_1(maximum_idx_by)
16149 fplus_fwd_flip_define_fn_1(maximum_idx_by_maybe)
16150 fplus_fwd_flip_define_fn_1(minimum_idx_on)
16151 fplus_fwd_flip_define_fn_1(minimum_idx_on_maybe)
16152 fplus_fwd_flip_define_fn_1(maximum_idx_on)
16153 fplus_fwd_flip_define_fn_1(maximum_idx_on_maybe)
16154 fplus_fwd_flip_define_fn_1(minimum_by)
16155 fplus_fwd_flip_define_fn_1(minimum_by_maybe)
16156 fplus_fwd_flip_define_fn_1(maximum_by)
16157 fplus_fwd_flip_define_fn_1(maximum_by_maybe)
16158 fplus_fwd_flip_define_fn_1(minimum_on)
16159 fplus_fwd_flip_define_fn_1(minimum_on_maybe)
16160 fplus_fwd_flip_define_fn_1(maximum_on)
16161 fplus_fwd_flip_define_fn_1(maximum_on_maybe)
16162 fplus_fwd_flip_define_fn_1(all_unique_by_less)
16163 fplus_fwd_flip_define_fn_1(is_infix_of)
16164 fplus_fwd_flip_define_fn_1(is_subsequence_of)
16165 fplus_fwd_flip_define_fn_1(count_if)
16166 fplus_fwd_flip_define_fn_1(count)
16167 fplus_fwd_flip_define_fn_1(is_unique_in_by)
16168 fplus_fwd_flip_define_fn_1(is_unique_in)
16169 fplus_fwd_flip_define_fn_1(is_permutation_of)
16170 fplus_fwd_flip_define_fn_1(fill_pigeonholes_to)
16171 fplus_fwd_flip_define_fn_1(fill_pigeonholes_bool_to)
16172 fplus_fwd_flip_define_fn_1(elem_at_idx_or_nothing)
16173 fplus_fwd_flip_define_fn_1(elem_at_idx_or_replicate)
16174 fplus_fwd_flip_define_fn_1(elem_at_idx_or_wrap)
16175 fplus_fwd_flip_define_fn_1(elem_at_float_idx)
16176 fplus_fwd_flip_define_fn_1(transform_map_values)
16177 fplus_fwd_flip_define_fn_1(map_union)
16178 fplus_fwd_flip_define_fn_1(create_map)
16179 fplus_fwd_flip_define_fn_1(create_map_with)
16180 fplus_fwd_flip_define_fn_1(create_map_grouped)
16181 fplus_fwd_flip_define_fn_1(create_unordered_map)
16182 fplus_fwd_flip_define_fn_1(create_unordered_map_with)
16183 fplus_fwd_flip_define_fn_1(create_unordered_map_grouped)
16184 fplus_fwd_flip_define_fn_1(get_from_map)
16185 fplus_fwd_flip_define_fn_1(get_from_map_unsafe)
16186 fplus_fwd_flip_define_fn_1(get_first_from_map)
16187 fplus_fwd_flip_define_fn_1(get_first_from_map_unsafe)
16188 fplus_fwd_flip_define_fn_1(map_contains)
16189 fplus_fwd_flip_define_fn_1(map_keep_if)
16190 fplus_fwd_flip_define_fn_1(map_drop_if)
16191 fplus_fwd_flip_define_fn_1(map_keep)
16192 fplus_fwd_flip_define_fn_1(map_drop)
16193 fplus_fwd_flip_define_fn_1(map_keep_if_value)
16194 fplus_fwd_flip_define_fn_1(map_drop_if_value)
16195 fplus_fwd_flip_define_fn_1(map_keep_values)
16196 fplus_fwd_flip_define_fn_1(map_drop_values)
16197 fplus_fwd_flip_define_fn_1(map_pluck)
16198 fplus_fwd_flip_define_fn_1(choose)
16199 fplus_fwd_flip_define_fn_1(choose_lazy)
16200 fplus_fwd_flip_define_fn_1(choose_def)
16201 fplus_fwd_flip_define_fn_1(choose_def_lazy)
16202 fplus_fwd_flip_define_fn_1(group_by)
16203 fplus_fwd_flip_define_fn_1(group_on)
16204 fplus_fwd_flip_define_fn_1(group_on_labeled)
16205 fplus_fwd_flip_define_fn_1(group_globally_by)
16206 fplus_fwd_flip_define_fn_1(group_globally_on)
16207 fplus_fwd_flip_define_fn_1(group_globally_on_labeled)
16208 fplus_fwd_flip_define_fn_1(cluster_by)
16209 fplus_fwd_flip_define_fn_1(split_by_keep_separators)
16210 fplus_fwd_flip_define_fn_1(split_keep_separators)
16211 fplus_fwd_flip_define_fn_1(split_at_idx)
16212 fplus_fwd_flip_define_fn_1(partition)
16213 fplus_fwd_flip_define_fn_1(split_at_idxs)
16214 fplus_fwd_flip_define_fn_1(split_every)
16215 fplus_fwd_flip_define_fn_1(run_length_encode_by)
16216 fplus_fwd_flip_define_fn_1(span)
16217 fplus_fwd_flip_define_fn_1(aperture)
16218 fplus_fwd_flip_define_fn_1(stride)
16219 fplus_fwd_flip_define_fn_1(winsorize)
16220 fplus_fwd_flip_define_fn_1(separate_on)
16221 fplus_fwd_flip_define_fn_1(transform_with_idx)
16222 fplus_fwd_flip_define_fn_1(transform_and_keep_justs)
16223 fplus_fwd_flip_define_fn_1(transform_and_keep_oks)
16224 fplus_fwd_flip_define_fn_1(transform_and_concat)
16225 fplus_fwd_flip_define_fn_1(replicate_elems)
16226 fplus_fwd_flip_define_fn_1(shuffle)
16227 fplus_fwd_flip_define_fn_1(random_element)
16228 fplus_fwd_flip_define_fn_1(apply_functions)
16229 fplus_fwd_flip_define_fn_1(transform_parallelly)
16230 fplus_fwd_flip_define_fn_1(reduce_1_parallelly)
16231 fplus_fwd_flip_define_fn_1(keep_if_parallelly)
16232 fplus_fwd_flip_define_fn_1(read_value_with_default)
16233 fplus_fwd_flip_define_fn_1(show_cont_with)
16234 fplus_fwd_flip_define_fn_1(split_words)
16235 fplus_fwd_flip_define_fn_1(split_lines)
16236 fplus_fwd_flip_define_fn_1(to_lower_case_loc)
16237 fplus_fwd_flip_define_fn_1(to_upper_case_loc)
16238 fplus_fwd_flip_define_fn_1(trees_from_sequence)
16239 fplus_fwd_flip_define_fn_1(are_trees_equal)
16240 
16241 } // namespace fwd
16242 } // namespace fplus
16243