I'm using boost::hana, and I'd like to filter a boost::hana::set.
#include <boost/hana.hpp>
#include <type_traits>
int main(){
using namespace boost::hana;
auto a = make_set(1,'a',3);
auto b = remove_if(a, [](const auto& x){return bool_c<std::is_same_v<decltype(x), char>>;});
// expects b to be make_set(1, 3);
}
This results in a static_assert failure. It tells me:
static assertion failed: hana::remove_if(xs, predicate) requires 'xs' to be a MonadPlus
static_assert(hana::MonadPlus<M>::value,
Why does this fail? Why can't a set be a MonadPlus, even though the empty set and the concatenation operation is defined?
If you want to filter a list you should use hana::tuple
. The idea of a Set is more general than MonadPlus or even Monad. Your assertion that hana::set
has implementations for hana::concat
or hana::empty
is incorrect, and besides it also requires the data structure to be a Monad.
Base on your example, perhaps what you are looking for is hana::difference
, but hana::set
itself is pretty useless for this. It's operations require hana::Comparable
and don't play well with run-time state.
If you want to "filter" sets by their type and maintain run-time values, I suggest using hana::map
which also supports set operations. You can make its keys the hana::type
of its value. This still requires uniqueness by its type.
Here is an example:
#include <boost/hana.hpp>
namespace hana = boost::hana;
constexpr auto typed_set = [](auto&& ...x) {
return hana::make_map(
hana::make_pair(hana::typeid_(x), std::forward<decltype(x)>(x))...
);
};
int main() {
auto a = typed_set(1, 'a', 3.0f);
auto b = typed_set('c');
auto c = hana::difference(a, b);
BOOST_HANA_RUNTIME_ASSERT(c == typed_set(1, 3.0f));
}