mirror of
https://github.com/boostorg/hana.git
synced 2026-02-22 03:22:21 +00:00
Typeclasses: move provided instances for non-builtin types out of the forward decls.
This commit is contained in:
@@ -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 <boost/hana/applicative/mcd.hpp>
|
||||
#include <boost/hana/comparable/equal_mcd.hpp>
|
||||
#include <boost/hana/core.hpp> // for instantiates and convert
|
||||
#include <boost/hana/detail/constexpr.hpp>
|
||||
#include <boost/hana/detail/std/type_traits.hpp>
|
||||
#include <boost/hana/foldable/foldable.hpp>
|
||||
#include <boost/hana/functor/fmap_mcd.hpp>
|
||||
#include <boost/hana/iterable/iterable.hpp>
|
||||
#include <boost/hana/logical/logical.hpp>
|
||||
#include <boost/hana/maybe.hpp>
|
||||
#include <boost/hana/monad/flatten_mcd.hpp>
|
||||
#include <boost/hana/searchable/find_mcd.hpp>
|
||||
#include <boost/hana/traversable/traverse_mcd.hpp>
|
||||
#include <boost/hana/detail/typeclasses.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace hana {
|
||||
@@ -361,159 +351,6 @@ namespace boost { namespace hana {
|
||||
datatype_t<decltype(xs)>
|
||||
>::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 <typename T>
|
||||
struct Functor::instance<T, when<instantiates<List, T>()>>
|
||||
: Functor::fmap_mcd
|
||||
{
|
||||
template <typename F, typename Xs>
|
||||
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<T>, 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 <typename T>
|
||||
struct Applicative::instance<T, when<instantiates<List, T>()>>
|
||||
: Applicative::mcd
|
||||
{
|
||||
template <typename X>
|
||||
static constexpr auto lift_impl(X x)
|
||||
{ return cons(x, nil<T>); }
|
||||
|
||||
template <typename Fs, typename Xs>
|
||||
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 <typename T>
|
||||
struct Monad::instance<T, when<instantiates<List, T>()>>
|
||||
: Monad::flatten_mcd
|
||||
{
|
||||
template <typename Xss>
|
||||
static constexpr auto flatten_impl(Xss xss)
|
||||
{ return foldl(concat, nil<T>, 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 <typename T>
|
||||
struct Traversable::instance<T, when<instantiates<List, T>()>>
|
||||
: Traversable::traverse_mcd
|
||||
{
|
||||
template <typename A, typename F, typename Xs>
|
||||
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<A>(nil<T>), 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 <typename T, typename U>
|
||||
struct Comparable::instance<T, U, when<
|
||||
instantiates<List, T>() && instantiates<List, U>()
|
||||
>> : Comparable::equal_mcd
|
||||
{
|
||||
template <typename Xs, typename Ys>
|
||||
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 <typename T>
|
||||
struct Searchable::instance<T, when<instantiates<List, T>()>>
|
||||
: Searchable::find_mcd
|
||||
{
|
||||
template <typename Pred, typename Xs>
|
||||
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 <typename Pred, typename Xs>
|
||||
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 <typename L, typename T>
|
||||
struct convert<L, T, detail::std::enable_if_t<
|
||||
instantiates<List, L>() && instantiates<Foldable, T>()
|
||||
>> {
|
||||
template <typename Xs>
|
||||
static constexpr auto apply(Xs xs)
|
||||
{ return foldr(cons, nil<L>, xs); }
|
||||
};
|
||||
}} // end namespace boost::hana
|
||||
|
||||
#endif // !BOOST_HANA_LIST_LIST_HPP
|
||||
|
||||
@@ -12,16 +12,21 @@ Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
#include <boost/hana/list/list.hpp>
|
||||
|
||||
#include <boost/hana/applicative/applicative.hpp>
|
||||
#include <boost/hana/applicative/mcd.hpp>
|
||||
#include <boost/hana/comparable/equal_mcd.hpp>
|
||||
#include <boost/hana/core.hpp> // for instantiates and convert
|
||||
#include <boost/hana/detail/right_folds/variadic_unrolled.hpp>
|
||||
#include <boost/hana/foldable/foldable.hpp>
|
||||
#include <boost/hana/functor/functor.hpp>
|
||||
#include <boost/hana/functor/fmap_mcd.hpp>
|
||||
#include <boost/hana/integral.hpp>
|
||||
#include <boost/hana/iterable/iterable.hpp>
|
||||
#include <boost/hana/logical/logical.hpp>
|
||||
#include <boost/hana/monad/monad.hpp>
|
||||
#include <boost/hana/maybe.hpp>
|
||||
#include <boost/hana/monad/flatten_mcd.hpp>
|
||||
#include <boost/hana/orderable/orderable.hpp>
|
||||
#include <boost/hana/pair/instance.hpp>
|
||||
#include <boost/hana/searchable/find_mcd.hpp>
|
||||
#include <boost/hana/traversable/traverse_mcd.hpp>
|
||||
|
||||
|
||||
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 <typename T>
|
||||
struct Functor::instance<T, when<instantiates<List, T>()>>
|
||||
: Functor::fmap_mcd
|
||||
{
|
||||
template <typename F, typename Xs>
|
||||
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<T>, 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 <typename T>
|
||||
struct Applicative::instance<T, when<instantiates<List, T>()>>
|
||||
: Applicative::mcd
|
||||
{
|
||||
template <typename X>
|
||||
static constexpr auto lift_impl(X x)
|
||||
{ return cons(x, nil<T>); }
|
||||
|
||||
template <typename Fs, typename Xs>
|
||||
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 <typename T>
|
||||
struct Monad::instance<T, when<instantiates<List, T>()>>
|
||||
: Monad::flatten_mcd
|
||||
{
|
||||
template <typename Xss>
|
||||
static constexpr auto flatten_impl(Xss xss)
|
||||
{ return foldl(concat, nil<T>, 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 <typename T>
|
||||
struct Traversable::instance<T, when<instantiates<List, T>()>>
|
||||
: Traversable::traverse_mcd
|
||||
{
|
||||
template <typename A, typename F, typename Xs>
|
||||
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<A>(nil<T>), 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 <typename T, typename U>
|
||||
struct Comparable::instance<T, U, when<
|
||||
instantiates<List, T>() && instantiates<List, U>()
|
||||
>> : Comparable::equal_mcd
|
||||
{
|
||||
template <typename Xs, typename Ys>
|
||||
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 <typename T>
|
||||
struct Searchable::instance<T, when<instantiates<List, T>()>>
|
||||
: Searchable::find_mcd
|
||||
{
|
||||
template <typename Pred, typename Xs>
|
||||
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 <typename Pred, typename Xs>
|
||||
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 <typename L, typename T>
|
||||
struct convert<L, T, detail::std::enable_if_t<
|
||||
instantiates<List, L>() && instantiates<Foldable, T>()
|
||||
>> {
|
||||
template <typename Xs>
|
||||
static constexpr auto apply(Xs xs)
|
||||
{ return foldr(cons, nil<L>, xs); }
|
||||
};
|
||||
}} // end namespace boost::hana
|
||||
|
||||
#endif // !BOOST_HANA_LIST_MCD_HPP
|
||||
|
||||
@@ -12,10 +12,88 @@ Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
#include <boost/hana/pair/pair.hpp>
|
||||
|
||||
#include <boost/hana/comparable/equal_mcd.hpp>
|
||||
#include <boost/hana/core.hpp> // for instantiates
|
||||
#include <boost/hana/logical/logical.hpp>
|
||||
|
||||
|
||||
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 <typename T, typename U>
|
||||
struct Comparable::instance<T, U, when<
|
||||
instantiates<Pair, T>() && instantiates<Pair, U>()
|
||||
>> : Comparable::equal_mcd {
|
||||
template <typename X, typename Y>
|
||||
static constexpr auto equal_impl(X x, Y y) {
|
||||
return and_(
|
||||
equal(first(x), first(y)),
|
||||
equal(second(x), second(y))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
template <typename T>
|
||||
struct Functor::instance<T, when<instantiates<Pair, T>()>>
|
||||
: Functor::fmap_mcd
|
||||
{
|
||||
template <typename F, typename P>
|
||||
static constexpr auto fmap_impl(F f, P p)
|
||||
{ return pair(f(first(p)), f(second(p))); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Applicative::instance<T, when<instantiates<Pair, T>()>>
|
||||
: Applicative::mcd
|
||||
{
|
||||
template <typename X>
|
||||
static constexpr auto lift_impl(X x)
|
||||
{ return pair(x, x); }
|
||||
|
||||
template <typename F, typename P>
|
||||
static constexpr auto ap_impl(F f, P p)
|
||||
{ return pair(first(f)(first(p), second(f)(second(p)))); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Monad::instance<T, when<instantiates<Pair, T>()>>
|
||||
: Monad::bind_mcd
|
||||
{
|
||||
template <typename P, typename F>
|
||||
static constexpr auto bind_impl(P p, F f) {
|
||||
return pair(
|
||||
bind(first(p), compose(first, f)),
|
||||
bind(second(p), compose(second, f))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Foldable::instance<T, when<instantiates<Pair, T>()>>
|
||||
: Foldable::mcd
|
||||
{
|
||||
template <typename F, typename S, typename P>
|
||||
static constexpr auto foldr_impl(F f, S s, P p) {
|
||||
return f(first(p), f(second(p), s));
|
||||
}
|
||||
|
||||
template <typename F, typename S, typename P>
|
||||
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
|
||||
|
||||
@@ -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 <boost/hana/comparable/equal_mcd.hpp>
|
||||
#include <boost/hana/core.hpp> // for instantiates
|
||||
#include <boost/hana/detail/constexpr.hpp>
|
||||
#include <boost/hana/logical/logical.hpp>
|
||||
#include <boost/hana/detail/typeclasses.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace hana {
|
||||
@@ -56,80 +54,6 @@ namespace boost { namespace hana {
|
||||
datatype_t<decltype(pair)>
|
||||
>::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 <typename T, typename U>
|
||||
struct Comparable::instance<T, U, when<
|
||||
instantiates<Pair, T>() && instantiates<Pair, U>()
|
||||
>> : Comparable::equal_mcd {
|
||||
template <typename X, typename Y>
|
||||
static constexpr auto equal_impl(X x, Y y) {
|
||||
return and_(
|
||||
equal(first(x), first(y)),
|
||||
equal(second(x), second(y))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
template <typename T>
|
||||
struct Functor::instance<T, when<instantiates<Pair, T>()>>
|
||||
: Functor::fmap_mcd
|
||||
{
|
||||
template <typename F, typename P>
|
||||
static constexpr auto fmap_impl(F f, P p)
|
||||
{ return pair(f(first(p)), f(second(p))); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Applicative::instance<T, when<instantiates<Pair, T>()>>
|
||||
: Applicative::mcd
|
||||
{
|
||||
template <typename X>
|
||||
static constexpr auto lift_impl(X x)
|
||||
{ return pair(x, x); }
|
||||
|
||||
template <typename F, typename P>
|
||||
static constexpr auto ap_impl(F f, P p)
|
||||
{ return pair(first(f)(first(p), second(f)(second(p)))); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Monad::instance<T, when<instantiates<Pair, T>()>>
|
||||
: Monad::bind_mcd
|
||||
{
|
||||
template <typename P, typename F>
|
||||
static constexpr auto bind_impl(P p, F f) {
|
||||
return pair(
|
||||
bind(first(p), compose(first, f)),
|
||||
bind(second(p), compose(second, f))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Foldable::instance<T, when<instantiates<Pair, T>()>>
|
||||
: Foldable::mcd
|
||||
{
|
||||
template <typename F, typename S, typename P>
|
||||
static constexpr auto foldr_impl(F f, S s, P p) {
|
||||
return f(first(p), f(second(p), s));
|
||||
}
|
||||
|
||||
template <typename F, typename S, typename P>
|
||||
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
|
||||
|
||||
@@ -12,11 +12,88 @@ Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
#include <boost/hana/record/record.hpp>
|
||||
|
||||
#include <boost/hana/comparable/equal_mcd.hpp>
|
||||
#include <boost/hana/core.hpp> // for instantiates
|
||||
#include <boost/hana/detail/std/type_traits.hpp>
|
||||
#include <boost/hana/foldable/mcd.hpp>
|
||||
#include <boost/hana/map.hpp>
|
||||
#include <boost/hana/pair/instance.hpp>
|
||||
#include <boost/hana/searchable/find_mcd.hpp>
|
||||
|
||||
|
||||
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<R>`.
|
||||
template <typename R>
|
||||
struct Comparable::instance<R, R, when<instantiates<Record, R>()>>
|
||||
: Comparable::equal_mcd
|
||||
{
|
||||
template <typename X, typename Y>
|
||||
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<R>);
|
||||
}
|
||||
};
|
||||
|
||||
//! Folding a `Record` `R` is equivalent to folding a list of its members,
|
||||
//! in the same order as they appear in `members<R>`.
|
||||
template <typename R>
|
||||
struct Foldable::instance<R, when<instantiates<Record, R>()>>
|
||||
: Foldable::mcd
|
||||
{
|
||||
template <typename F, typename S, typename X>
|
||||
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<R>);
|
||||
}
|
||||
|
||||
template <typename F, typename S, typename X>
|
||||
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<R>);
|
||||
}
|
||||
};
|
||||
|
||||
//! Searching a `Record` `r` is equivalent to searching `to<Map>(r)`.
|
||||
template <typename R>
|
||||
struct Searchable::instance<R, when<instantiates<Record, R>()>>
|
||||
: Searchable::find_mcd
|
||||
{
|
||||
template <typename Pred, typename X>
|
||||
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<R>)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Pred, typename X>
|
||||
static constexpr auto any_impl(Pred pred, X x) {
|
||||
return any([=](auto k_f) { return pred(first(k_f)); }, members<R>);
|
||||
}
|
||||
};
|
||||
|
||||
//! Converting a `Record` `R` to a `Map` is equivalent to converting its
|
||||
//! `members<R>` to a `Map`, except the values are replaced by the actual
|
||||
//! members of the object instead of accessors.
|
||||
template <typename R>
|
||||
struct convert<Map, R, detail::std::enable_if_t<instantiates<Record, R>()>> {
|
||||
template <typename X>
|
||||
static constexpr auto apply(X x) {
|
||||
return to<Map>(fmap(
|
||||
[=](auto k_f) { return pair(first(k_f), second(k_f)(x)); },
|
||||
members<R>
|
||||
));
|
||||
}
|
||||
};
|
||||
}} // end namespace boost::hana
|
||||
|
||||
|
||||
@@ -40,87 +40,4 @@ namespace boost { namespace hana {
|
||||
BOOST_HANA_CONSTEXPR_LAMBDA auto members = Record::instance<R>::members_impl();
|
||||
}} // end namespace boost::hana
|
||||
|
||||
|
||||
#include <boost/hana/comparable/equal_mcd.hpp>
|
||||
#include <boost/hana/core.hpp> // for instantiates
|
||||
#include <boost/hana/detail/std/type_traits.hpp>
|
||||
#include <boost/hana/foldable/mcd.hpp>
|
||||
#include <boost/hana/map.hpp>
|
||||
#include <boost/hana/pair/instance.hpp>
|
||||
#include <boost/hana/searchable/find_mcd.hpp>
|
||||
|
||||
|
||||
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<R>`.
|
||||
template <typename R>
|
||||
struct Comparable::instance<R, R, when<instantiates<Record, R>()>>
|
||||
: Comparable::equal_mcd
|
||||
{
|
||||
template <typename X, typename Y>
|
||||
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<R>);
|
||||
}
|
||||
};
|
||||
|
||||
//! Folding a `Record` `R` is equivalent to folding a list of its members,
|
||||
//! in the same order as they appear in `members<R>`.
|
||||
template <typename R>
|
||||
struct Foldable::instance<R, when<instantiates<Record, R>()>>
|
||||
: Foldable::mcd
|
||||
{
|
||||
template <typename F, typename S, typename X>
|
||||
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<R>);
|
||||
}
|
||||
|
||||
template <typename F, typename S, typename X>
|
||||
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<R>);
|
||||
}
|
||||
};
|
||||
|
||||
//! Searching a `Record` `r` is equivalent to searching `to<Map>(r)`.
|
||||
template <typename R>
|
||||
struct Searchable::instance<R, when<instantiates<Record, R>()>>
|
||||
: Searchable::find_mcd
|
||||
{
|
||||
template <typename Pred, typename X>
|
||||
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<R>)
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Pred, typename X>
|
||||
static constexpr auto any_impl(Pred pred, X x) {
|
||||
return any([=](auto k_f) { return pred(first(k_f)); }, members<R>);
|
||||
}
|
||||
};
|
||||
|
||||
//! Converting a `Record` `R` to a `Map` is equivalent to converting its
|
||||
//! `members<R>` to a `Map`, except the values are replaced by the actual
|
||||
//! members of the object instead of accessors.
|
||||
template <typename R>
|
||||
struct convert<Map, R, detail::std::enable_if_t<instantiates<Record, R>()>> {
|
||||
template <typename X>
|
||||
static constexpr auto apply(X x) {
|
||||
return to<Map>(fmap(
|
||||
[=](auto k_f) { return pair(first(k_f), second(k_f)(x)); },
|
||||
members<R>
|
||||
));
|
||||
}
|
||||
};
|
||||
}} // end namespace boost::hana
|
||||
|
||||
#endif // !BOOST_HANA_RECORD_RECORD_HPP
|
||||
|
||||
Reference in New Issue
Block a user