diff --git a/include/boost/hana/list/list.hpp b/include/boost/hana/list/list.hpp index e67b9dbe0..a802fb949 100644 --- a/include/boost/hana/list/list.hpp +++ b/include/boost/hana/list/list.hpp @@ -10,19 +10,9 @@ Distributed under the Boost Software License, Version 1.0. #ifndef BOOST_HANA_LIST_LIST_HPP #define BOOST_HANA_LIST_LIST_HPP -#include -#include -#include // for instantiates and convert #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include namespace boost { namespace hana { @@ -361,159 +351,6 @@ namespace boost { namespace hana { datatype_t >::zip_with_impl(f, xs, ys...); }; - - //! @details - //! `List`s implement `fmap` as the mapping of a function over each - //! element of the list. This is somewhat equivalent to `std::transform`. - //! Mapping a function over an empty list returns an empty list and never - //! applies the function. - //! - //! ### Example 1 - //! @snippet example/list/functor/fmap.cpp main - //! - //! ### Example 2 - //! @snippet example/type_list/functor/fmap.cpp main - template - struct Functor::instance()>> - : Functor::fmap_mcd - { - template - static constexpr auto fmap_impl(F f, Xs xs) { - auto cons_f = [=](auto x, auto xs) { return cons(f(x), xs); }; - return foldr(cons_f, nil, xs); - } - }; - - //! @details - //! A value can be lifted into a singleton list with `lift`. `ap(fs, xs)` - //! applies each function in the list `fs` to each value in the list `xs`, - //! and returns a list containing all the results. - //! - //! ### Example - //! @snippet example/list/applicative/overview.cpp main - template - struct Applicative::instance()>> - : Applicative::mcd - { - template - static constexpr auto lift_impl(X x) - { return cons(x, nil); } - - template - static constexpr auto ap_impl(Fs fs, Xs xs) - { return bind(fs, [=](auto f) { return fmap(f, xs); }); } - }; - - //! @details - //! A function returning a list of results can be mapped over all the - //! elements of a list and have all the results concatenated using `bind`. - //! Also, a list of lists can be flattened one level with `flatten`. - //! - //! ### Example - //! @snippet example/list/monad/overview.cpp main - template - struct Monad::instance()>> - : Monad::flatten_mcd - { - template - static constexpr auto flatten_impl(Xss xss) - { return foldl(concat, nil, xss); } - }; - - //! @details - //! This instance is hard to describe in words; see the examples. - //! - //! ### Example - //! @snippet example/list/traversable/traverse.cpp main - //! - //! ### Example - //! @snippet example/list/traversable/sequence.cpp main - template - struct Traversable::instance()>> - : Traversable::traverse_mcd - { - template - static constexpr auto traverse_impl(F f, Xs xs) { - auto curried_cons = [](auto x) { - return [=](auto xs) { return cons(x, xs); }; - }; - auto cons_f = [=](auto x, auto ys) { - return ap(fmap(curried_cons, f(x)), ys); - }; - return foldr(cons_f, lift(nil), xs); - } - }; - - //! @details - //! Two `List`s are equal if and only if they contain the same number - //! of elements and their elements at any given index are equal. - //! - //! ### Example - //! @snippet example/list/comparable.cpp main - template - struct Comparable::instance() && instantiates() - >> : Comparable::equal_mcd - { - template - static constexpr auto equal_impl(Xs xs, Ys ys) { - return eval_if(or_(is_empty(xs), is_empty(ys)), - [=](auto _) { - return and_(_(is_empty)(xs), _(is_empty)(ys)); - }, - [=](auto _) { - return and_(equal(_(head)(xs), _(head)(ys)), - equal_impl(_(tail)(xs), _(tail)(ys))); - } - ); - } - }; - - //! @details - //! A `List` can be searched by doing a linear search in the elements, - //! with the keys and values being both the elements in the list. - //! - //! @todo - //! Technically, this can be implemented in `Iterable`. Should it? - //! - //! ### Example - //! @snippet example/list/searchable/find.cpp main - template - struct Searchable::instance()>> - : Searchable::find_mcd - { - template - static constexpr auto find_impl(Pred pred, Xs xs) { - auto e = drop_until(pred, xs); - return eval_if(is_empty(e), - [](auto) { return nothing; }, - [=](auto _) { return just(_(head)(e)); } - ); - } - - template - static constexpr auto any_impl(Pred pred, Xs xs) { - return eval_if(is_empty(xs), - [](auto _) { return false_; }, - [=](auto _) { - return eval_if(pred(_(head)(xs)), - [=](auto _) { return true_; }, - [=](auto _) { return any_impl(pred, _(tail)(xs)); } - ); - } - ); - } - }; - - //! Converts a `Foldable` to a `List`. - template - struct convert() && instantiates() - >> { - template - static constexpr auto apply(Xs xs) - { return foldr(cons, nil, xs); } - }; }} // end namespace boost::hana #endif // !BOOST_HANA_LIST_LIST_HPP diff --git a/include/boost/hana/list/mcd.hpp b/include/boost/hana/list/mcd.hpp index 473e1d92b..b81cb15f5 100644 --- a/include/boost/hana/list/mcd.hpp +++ b/include/boost/hana/list/mcd.hpp @@ -12,16 +12,21 @@ Distributed under the Boost Software License, Version 1.0. #include -#include +#include +#include +#include // for instantiates and convert #include #include -#include +#include #include #include #include -#include +#include +#include #include #include +#include +#include namespace boost { namespace hana { @@ -231,6 +236,159 @@ namespace boost { namespace hana { ); } }; + + //! @details + //! `List`s implement `fmap` as the mapping of a function over each + //! element of the list. This is somewhat equivalent to `std::transform`. + //! Mapping a function over an empty list returns an empty list and never + //! applies the function. + //! + //! ### Example 1 + //! @snippet example/list/functor/fmap.cpp main + //! + //! ### Example 2 + //! @snippet example/type_list/functor/fmap.cpp main + template + struct Functor::instance()>> + : Functor::fmap_mcd + { + template + static constexpr auto fmap_impl(F f, Xs xs) { + auto cons_f = [=](auto x, auto xs) { return cons(f(x), xs); }; + return foldr(cons_f, nil, xs); + } + }; + + //! @details + //! A value can be lifted into a singleton list with `lift`. `ap(fs, xs)` + //! applies each function in the list `fs` to each value in the list `xs`, + //! and returns a list containing all the results. + //! + //! ### Example + //! @snippet example/list/applicative/overview.cpp main + template + struct Applicative::instance()>> + : Applicative::mcd + { + template + static constexpr auto lift_impl(X x) + { return cons(x, nil); } + + template + static constexpr auto ap_impl(Fs fs, Xs xs) + { return bind(fs, [=](auto f) { return fmap(f, xs); }); } + }; + + //! @details + //! A function returning a list of results can be mapped over all the + //! elements of a list and have all the results concatenated using `bind`. + //! Also, a list of lists can be flattened one level with `flatten`. + //! + //! ### Example + //! @snippet example/list/monad/overview.cpp main + template + struct Monad::instance()>> + : Monad::flatten_mcd + { + template + static constexpr auto flatten_impl(Xss xss) + { return foldl(concat, nil, xss); } + }; + + //! @details + //! This instance is hard to describe in words; see the examples. + //! + //! ### Example + //! @snippet example/list/traversable/traverse.cpp main + //! + //! ### Example + //! @snippet example/list/traversable/sequence.cpp main + template + struct Traversable::instance()>> + : Traversable::traverse_mcd + { + template + static constexpr auto traverse_impl(F f, Xs xs) { + auto curried_cons = [](auto x) { + return [=](auto xs) { return cons(x, xs); }; + }; + auto cons_f = [=](auto x, auto ys) { + return ap(fmap(curried_cons, f(x)), ys); + }; + return foldr(cons_f, lift(nil), xs); + } + }; + + //! @details + //! Two `List`s are equal if and only if they contain the same number + //! of elements and their elements at any given index are equal. + //! + //! ### Example + //! @snippet example/list/comparable.cpp main + template + struct Comparable::instance() && instantiates() + >> : Comparable::equal_mcd + { + template + static constexpr auto equal_impl(Xs xs, Ys ys) { + return eval_if(or_(is_empty(xs), is_empty(ys)), + [=](auto _) { + return and_(_(is_empty)(xs), _(is_empty)(ys)); + }, + [=](auto _) { + return and_(equal(_(head)(xs), _(head)(ys)), + equal_impl(_(tail)(xs), _(tail)(ys))); + } + ); + } + }; + + //! @details + //! A `List` can be searched by doing a linear search in the elements, + //! with the keys and values being both the elements in the list. + //! + //! @todo + //! Technically, this can be implemented in `Iterable`. Should it? + //! + //! ### Example + //! @snippet example/list/searchable/find.cpp main + template + struct Searchable::instance()>> + : Searchable::find_mcd + { + template + static constexpr auto find_impl(Pred pred, Xs xs) { + auto e = drop_until(pred, xs); + return eval_if(is_empty(e), + [](auto) { return nothing; }, + [=](auto _) { return just(_(head)(e)); } + ); + } + + template + static constexpr auto any_impl(Pred pred, Xs xs) { + return eval_if(is_empty(xs), + [](auto _) { return false_; }, + [=](auto _) { + return eval_if(pred(_(head)(xs)), + [=](auto _) { return true_; }, + [=](auto _) { return any_impl(pred, _(tail)(xs)); } + ); + } + ); + } + }; + + //! Converts a `Foldable` to a `List`. + template + struct convert() && instantiates() + >> { + template + static constexpr auto apply(Xs xs) + { return foldr(cons, nil, xs); } + }; }} // end namespace boost::hana #endif // !BOOST_HANA_LIST_MCD_HPP diff --git a/include/boost/hana/pair/mcd.hpp b/include/boost/hana/pair/mcd.hpp index 847ec0559..5e0fd9bf6 100644 --- a/include/boost/hana/pair/mcd.hpp +++ b/include/boost/hana/pair/mcd.hpp @@ -12,10 +12,88 @@ Distributed under the Boost Software License, Version 1.0. #include +#include +#include // for instantiates +#include + namespace boost { namespace hana { //! Minimal complete definition: `first` and `second` struct Pair::mcd { }; + + //! @details + //! Two pairs `x` and `y` are equal iff they are equal element-wise, + //! i.e. iff + //! @code + //! first(x) == first(y) && second(x) == second(y) + //! @endcode + //! + //! ### Example + //! @snippet example/pair/comparable.cpp main + template + struct Comparable::instance() && instantiates() + >> : Comparable::equal_mcd { + template + static constexpr auto equal_impl(X x, Y y) { + return and_( + equal(first(x), first(y)), + equal(second(x), second(y)) + ); + } + }; + +#if 0 + template + struct Functor::instance()>> + : Functor::fmap_mcd + { + template + static constexpr auto fmap_impl(F f, P p) + { return pair(f(first(p)), f(second(p))); } + }; + + template + struct Applicative::instance()>> + : Applicative::mcd + { + template + static constexpr auto lift_impl(X x) + { return pair(x, x); } + + template + static constexpr auto ap_impl(F f, P p) + { return pair(first(f)(first(p), second(f)(second(p)))); } + }; + + template + struct Monad::instance()>> + : Monad::bind_mcd + { + template + static constexpr auto bind_impl(P p, F f) { + return pair( + bind(first(p), compose(first, f)), + bind(second(p), compose(second, f)) + ); + } + }; + + template + struct Foldable::instance()>> + : Foldable::mcd + { + template + static constexpr auto foldr_impl(F f, S s, P p) { + return f(first(p), f(second(p), s)); + } + + template + static constexpr auto foldl_impl(F f, S s, P p) { + return f(f(s, first(p)), second(p)); + } + }; +#endif }} // end namespace boost::hana #endif // !BOOST_HANA_PAIR_MCD_HPP diff --git a/include/boost/hana/pair/pair.hpp b/include/boost/hana/pair/pair.hpp index e9b532eae..943931356 100644 --- a/include/boost/hana/pair/pair.hpp +++ b/include/boost/hana/pair/pair.hpp @@ -10,10 +10,8 @@ Distributed under the Boost Software License, Version 1.0. #ifndef BOOST_HANA_PAIR_PAIR_HPP #define BOOST_HANA_PAIR_PAIR_HPP -#include -#include // for instantiates #include -#include +#include namespace boost { namespace hana { @@ -56,80 +54,6 @@ namespace boost { namespace hana { datatype_t >::second_impl(pair); }; - - //! @details - //! Two pairs `x` and `y` are equal iff they are equal element-wise, - //! i.e. iff - //! @code - //! first(x) == first(y) && second(x) == second(y) - //! @endcode - //! - //! ### Example - //! @snippet example/pair/comparable.cpp main - template - struct Comparable::instance() && instantiates() - >> : Comparable::equal_mcd { - template - static constexpr auto equal_impl(X x, Y y) { - return and_( - equal(first(x), first(y)), - equal(second(x), second(y)) - ); - } - }; - -#if 0 - template - struct Functor::instance()>> - : Functor::fmap_mcd - { - template - static constexpr auto fmap_impl(F f, P p) - { return pair(f(first(p)), f(second(p))); } - }; - - template - struct Applicative::instance()>> - : Applicative::mcd - { - template - static constexpr auto lift_impl(X x) - { return pair(x, x); } - - template - static constexpr auto ap_impl(F f, P p) - { return pair(first(f)(first(p), second(f)(second(p)))); } - }; - - template - struct Monad::instance()>> - : Monad::bind_mcd - { - template - static constexpr auto bind_impl(P p, F f) { - return pair( - bind(first(p), compose(first, f)), - bind(second(p), compose(second, f)) - ); - } - }; - - template - struct Foldable::instance()>> - : Foldable::mcd - { - template - static constexpr auto foldr_impl(F f, S s, P p) { - return f(first(p), f(second(p), s)); - } - - template - static constexpr auto foldl_impl(F f, S s, P p) { - return f(f(s, first(p)), second(p)); - } - }; -#endif }} // end namespace boost::hana #endif // !BOOST_HANA_PAIR_PAIR_HPP diff --git a/include/boost/hana/record/mcd.hpp b/include/boost/hana/record/mcd.hpp index 744a70e2a..55c11115a 100644 --- a/include/boost/hana/record/mcd.hpp +++ b/include/boost/hana/record/mcd.hpp @@ -12,11 +12,88 @@ Distributed under the Boost Software License, Version 1.0. #include +#include +#include // for instantiates +#include +#include +#include +#include +#include + namespace boost { namespace hana { //! Minimal complete definition: `members` - struct Record::mcd { + struct Record::mcd { }; + //! Two `Records` of the same data type `R` are equal if and only if + //! all their members are equal. The members are compared in the + //! same order as they appear in `members`. + template + struct Comparable::instance()>> + : Comparable::equal_mcd + { + template + static constexpr auto equal_impl(X x, Y y) { + return all([=](auto k_f) { + return equal(second(k_f)(x), second(k_f)(y)); + }, members); + } + }; + + //! Folding a `Record` `R` is equivalent to folding a list of its members, + //! in the same order as they appear in `members`. + template + struct Foldable::instance()>> + : Foldable::mcd + { + template + static constexpr auto foldl_impl(F f, S s, X x) { + auto g = [=](auto s, auto k_f) { + return f(s, second(k_f)(x)); + }; + return foldl(g, s, members); + } + + template + static constexpr auto foldr_impl(F f, S s, X x) { + auto g = [=](auto k_f, auto s) { + return f(second(k_f)(x), s); + }; + return foldr(g, s, members); + } + }; + + //! Searching a `Record` `r` is equivalent to searching `to(r)`. + template + struct Searchable::instance()>> + : Searchable::find_mcd + { + template + static constexpr auto find_impl(Pred pred, X x) { + return fmap( + [=](auto k_f) { return second(k_f)(x); }, + find([=](auto k_f) { return pred(first(k_f)); }, members) + ); + } + + template + static constexpr auto any_impl(Pred pred, X x) { + return any([=](auto k_f) { return pred(first(k_f)); }, members); + } + }; + + //! Converting a `Record` `R` to a `Map` is equivalent to converting its + //! `members` to a `Map`, except the values are replaced by the actual + //! members of the object instead of accessors. + template + struct convert()>> { + template + static constexpr auto apply(X x) { + return to(fmap( + [=](auto k_f) { return pair(first(k_f), second(k_f)(x)); }, + members + )); + } }; }} // end namespace boost::hana diff --git a/include/boost/hana/record/record.hpp b/include/boost/hana/record/record.hpp index 40f2b290e..8534d6ab1 100644 --- a/include/boost/hana/record/record.hpp +++ b/include/boost/hana/record/record.hpp @@ -40,87 +40,4 @@ namespace boost { namespace hana { BOOST_HANA_CONSTEXPR_LAMBDA auto members = Record::instance::members_impl(); }} // end namespace boost::hana - -#include -#include // for instantiates -#include -#include -#include -#include -#include - - -namespace boost { namespace hana { - //! Two `Records` of the same data type `R` are equal if and only if - //! all their members are equal. The members are compared in the - //! same order as they appear in `members`. - template - struct Comparable::instance()>> - : Comparable::equal_mcd - { - template - static constexpr auto equal_impl(X x, Y y) { - return all([=](auto k_f) { - return equal(second(k_f)(x), second(k_f)(y)); - }, members); - } - }; - - //! Folding a `Record` `R` is equivalent to folding a list of its members, - //! in the same order as they appear in `members`. - template - struct Foldable::instance()>> - : Foldable::mcd - { - template - static constexpr auto foldl_impl(F f, S s, X x) { - auto g = [=](auto s, auto k_f) { - return f(s, second(k_f)(x)); - }; - return foldl(g, s, members); - } - - template - static constexpr auto foldr_impl(F f, S s, X x) { - auto g = [=](auto k_f, auto s) { - return f(second(k_f)(x), s); - }; - return foldr(g, s, members); - } - }; - - //! Searching a `Record` `r` is equivalent to searching `to(r)`. - template - struct Searchable::instance()>> - : Searchable::find_mcd - { - template - static constexpr auto find_impl(Pred pred, X x) { - return fmap( - [=](auto k_f) { return second(k_f)(x); }, - find([=](auto k_f) { return pred(first(k_f)); }, members) - ); - } - - template - static constexpr auto any_impl(Pred pred, X x) { - return any([=](auto k_f) { return pred(first(k_f)); }, members); - } - }; - - //! Converting a `Record` `R` to a `Map` is equivalent to converting its - //! `members` to a `Map`, except the values are replaced by the actual - //! members of the object instead of accessors. - template - struct convert()>> { - template - static constexpr auto apply(X x) { - return to(fmap( - [=](auto k_f) { return pair(first(k_f), second(k_f)(x)); }, - members - )); - } - }; -}} // end namespace boost::hana - #endif // !BOOST_HANA_RECORD_RECORD_HPP