Boost.Hana  1.5.0
Your standard library for metaprogramming
MonadPlus

Description

The MonadPlus concept represents Monads with a monoidal structure.

Intuitively, whereas a Monad can be seen as some kind of container or context, a MonadPlus can be seen as a container or a context that can be concatenated with other containers or contexts. There must also be an identity element for this combining operation. For example, a tuple is a MonadPlus, because tuples can be concatenated and the empty tuple would act as an identity for concatenation. How is this different from a Monad which is also a Monoid? The answer is that the monoidal structure on a MonadPlus must not depend of the contents of the structure; it must not require the contents to be a Monoid in order to work.

While sequences are not the only possible model for MonadPlus, the method names used here refer to the MonadPlus of sequences under concatenation. Several useful functions generalizing operations on sequences are included with this concept, like append, prepend and filter.

Note
This documentation does not go into much details about the nature of the MonadPlus concept. However, there is a nice Haskell-oriented WikiBook going into further details.

Minimal complete definition

concat and empty

Laws

First, a MonadPlus is required to have a monoidal structure. Hence, it is no surprise that for any MonadPlus M, we require M(T) to be a valid monoid. However, we do not enforce that M(T) actually models the Monoid concept provided by Hana. Further, for all objects a, b, c of data type M(T),

// identity
concat(empty<M(T)>(), a) == a
concat(a, empty<M(T)>()) == a
// associativity
concat(a, concat(b, c)) == concat(concat(a, b), c)

Secondly, a MonadPlus is also required to obey the following laws, which represent the fact that empty<M(T)>() must be some kind of absorbing element for the chain operation. For all objects a of data type M(T) and functions \( f : T \to M(U) \),

chain(empty<M(T)>(), f) == empty<M(U)>()
chain(a, always(empty<M(T)>())) == empty<M(U)>()

Refined concepts

Functor, Applicative and Monad

Concrete models

hana::optional, hana::tuple

Variables

constexpr auto boost::hana::append
 Append an element to a monadic structure.Given an element x and a monadic structure xs, append returns a new monadic structure which is the result of lifting x into the monadic structure and then combining that (to the right) with xs. In other words,. More...
 
constexpr auto boost::hana::concat
 Combine two monadic structures together.Given two monadic structures, concat combines them together and returns a new monadic structure. The exact definition of concat will depend on the exact model of MonadPlus at hand, but for sequences it corresponds intuitively to simple concatenation. More...
 
constexpr auto boost::hana::cycle
 Combine a monadic structure with itself n times.Given a monadic structure xs and a non-negative number n, cycle returns a new monadic structure which is the result of combining xs with itself n times using the concat operation. In other words,. More...
 
template<typename M >
constexpr auto boost::hana::empty
 Identity of the monadic combination concat.

Signature

Given a MonadPlus M, the signature is \( \mathtt{empty}_M : \emptyset \to M(T) \). More...
 
constexpr auto boost::hana::filter
 Filter a monadic structure using a custom predicate.Given a monadic structure and a predicate, filter returns a new monadic structure containing only those elements that satisfy the predicate. This is a generalization of the usual filter function for sequences; it works for any MonadPlus. Intuitively, filter is somewhat equivalent to: More...
 
constexpr auto boost::hana::prefix
 Inserts a value before each element of a monadic structure.Given a monadic structure xs and a value z called the prefix, prefix returns a new monadic structure. prefix satisfies. More...
 
constexpr auto boost::hana::prepend
 Prepend an element to a monadic structure.Given a monadic structure xs and an element x, prepend returns a new monadic structure which is the result of lifting x into the monadic structure and then combining that (to the left) with xs. In other words,. More...
 
constexpr auto boost::hana::remove
 Remove all the elements of a monadic structure that are equal to some value.Given a monadic structure xs and a value, remove returns a new monadic structure equal to xs without all its elements that are equal to the given value. remove is equivalent to remove_if with the equal.to(value) predicate, i.e. More...
 
constexpr auto boost::hana::remove_if
 Remove all the elements of a monadic structure that satisfy some predicate.Given a monadic structure xs and a unary predicate, remove_if returns a new monadic structure equal to xs without all its elements that satisfy the predicate. This is equivalent to filter with a negated predicate, i.e. More...
 
template<typename M >
constexpr auto boost::hana::replicate
 Create a monadic structure by combining a lifted value with itself n times.Given a value x, a non-negative IntegralConstant n and the tag of a monadic structure M, replicate creates a new monadic structure which is the result of combining x with itself n times inside the monadic structure. In other words, replicate simply lifts x into the monadic structure, and then combines that with itself n times: More...
 
constexpr auto boost::hana::suffix
 Inserts a value after each element of a monadic structure.Given a monadic structure xs and a value z (called the suffix), suffix returns a new monadic structure such that. More...
 

Variable Documentation

constexpr auto boost::hana::append

#include <boost/hana/fwd/append.hpp>

Initial value:
= [](auto&& xs, auto&& x) {
return tag-dispatched;
}

Append an element to a monadic structure.Given an element x and a monadic structure xs, append returns a new monadic structure which is the result of lifting x into the monadic structure and then combining that (to the right) with xs. In other words,.

append(xs, x) == concat(xs, lift<Xs>(x))

where Xs is the tag of xs. For sequences, this has the intuitive behavior of simply appending an element to the end of the sequence, hence the name.

Rationale for not calling this push_back

See the rationale for using prepend instead of push_front.

Signature

Given a MonadPlus M, the signature is \( \mathtt{append} : M(T) \times T \to M(T) \).

Parameters
xsA monadic structure that will be combined to the left of the element.
xAn element to combine to the right of the monadic structure.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
static_assert(hana::append(hana::make_tuple(), 1) == hana::make_tuple(1), "");
static_assert(hana::append(hana::make_tuple(1, '2'), 3.3) == hana::make_tuple(1, '2', 3.3), "");
static_assert(hana::append(hana::append(hana::append(hana::make_tuple(), 1), '2'), 3.3) == hana::make_tuple(1, '2', 3.3), "");
int main() { }
constexpr auto boost::hana::concat

#include <boost/hana/fwd/concat.hpp>

Initial value:
= [](auto&& xs, auto&& ys) {
return tag-dispatched;
}

Combine two monadic structures together.Given two monadic structures, concat combines them together and returns a new monadic structure. The exact definition of concat will depend on the exact model of MonadPlus at hand, but for sequences it corresponds intuitively to simple concatenation.

Also note that combination is not required to be commutative. In other words, there is no requirement that

concat(xs, ys) == concat(ys, xs)

and indeed it does not hold in general.

Signature

Given a MonadPlus M, the signature of concat is \( \mathtt{concat} : M(T) \times M(T) \to M(T) \).

Parameters
xs,ysTwo monadic structures to combine together.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
using namespace hana::literals;
static_assert(
hana::concat(hana::make_tuple(1, '2'), hana::make_tuple(3.3, 4_c))
==
hana::make_tuple(1, '2', 3.3, 4_c)
, "");
int main() { }
constexpr auto boost::hana::cycle

#include <boost/hana/fwd/cycle.hpp>

Initial value:
= [](auto&& xs, auto const& n) {
return tag-dispatched;
}

Combine a monadic structure with itself n times.Given a monadic structure xs and a non-negative number n, cycle returns a new monadic structure which is the result of combining xs with itself n times using the concat operation. In other words,.

cycle(xs, n) == concat(xs, concat(xs, ... concat(xs, xs)))
// ^^^^^ n times total

Also note that since concat is required to be associative, we could also have written

cycle(xs, n) == concat(concat(... concat(xs, xs), xs), xs)
// ^^^^^ n times total

If n is zero, then the identity of concat, empty, is returned. In the case of sequences, this boils down to returning a sequence containing n copies of itself; for other models it might differ.

Signature

Given an IntegralConstant C and a MonadPlus M, the signature is \( \mathrm{cycle} : M(T) \times C \to M(T) \).

Parameters
xsA monadic structure to combine with itself a certain number of times.
nA non-negative IntegralConstant representing the number of times to combine the monadic structure with itself. If n is zero, cycle returns empty.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
static_assert(hana::cycle(hana::make_tuple('x', 'y'), hana::size_c<2>) == hana::make_tuple('x', 'y', 'x', 'y'), "");
int main() { }
template<typename M >
constexpr auto boost::hana::empty

#include <boost/hana/fwd/empty.hpp>

Initial value:
= []() {
return tag-dispatched;
}

Identity of the monadic combination concat.

Signature

Given a MonadPlus M, the signature is \( \mathtt{empty}_M : \emptyset \to M(T) \).

Template Parameters
MThe tag of the monadic structure to return. This must be a model of the MonadPlus concept.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
BOOST_HANA_CONSTANT_CHECK(hana::empty<hana::tuple_tag>() == hana::make_tuple());
BOOST_HANA_CONSTANT_CHECK(hana::empty<hana::optional_tag>() == hana::nothing);
int main() { }
constexpr auto boost::hana::filter

#include <boost/hana/fwd/filter.hpp>

Initial value:
= [](auto&& xs, auto&& pred) {
return tag-dispatched;
}

Filter a monadic structure using a custom predicate.Given a monadic structure and a predicate, filter returns a new monadic structure containing only those elements that satisfy the predicate. This is a generalization of the usual filter function for sequences; it works for any MonadPlus. Intuitively, filter is somewhat equivalent to:

filter(xs, pred) == flatten(transform(xs, [](auto x) {
return pred(x) ? lift<Xs>(x) : empty<Xs>();
})

In other words, we basically turn a monadic structure containing [x1, ..., xn] into a monadic structure containing

[
pred(x1) ? [x1] : [],
pred(x2) ? [x2] : [],
...
pred(xn) ? [xn] : []
]

and we then flatten that.

Signature

Given a MonadPlus M and an IntegralConstant Bool holding a value of type bool, the signature is \( \mathtt{filter} : M(T) \times (T \to \mathtt{Bool}) \to M(T) \).

Parameters
xsThe monadic structure to filter.
predA function called as pred(x) for each element x in the monadic structure and returning whether that element should be kept in the resulting structure. In the current version of the library, the predicate has to return an IntegralConstant holding a value convertible to a bool.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <type_traits>
namespace hana = boost::hana;
// First take the type of an object, and then tell whether it's integral
constexpr auto is_integral = hana::compose(hana::trait<std::is_integral>, hana::typeid_);
static_assert(hana::filter(hana::make_tuple(1, 2.0, 3, 4.0), is_integral) == hana::make_tuple(1, 3), "");
static_assert(hana::filter(hana::just(3), is_integral) == hana::just(3), "");
BOOST_HANA_CONSTANT_CHECK(hana::filter(hana::just(3.0), is_integral) == hana::nothing);
int main() { }
constexpr auto boost::hana::prefix

#include <boost/hana/fwd/prefix.hpp>

Initial value:
= [](auto&& xs, auto&& pref) {
return tag-dispatched;
}

Inserts a value before each element of a monadic structure.Given a monadic structure xs and a value z called the prefix, prefix returns a new monadic structure. prefix satisfies.

prefix(xs, z) == flatten(transform(xs, [](auto x) {
return concat(lift<M>(z), lift<M>(x));
}))

For sequences, this simply corresponds to inserting the prefix before each element of the sequence. For example, given a sequence [x1, ..., xn], prefix will return

[z, x1, z, x2, ..., z, xn]

As explained above, this can be generalized to other MonadPlus models, with various levels of interest.

Signature

Given a MonadPlus M, the signature is \( \mathrm{prefix} : M(T) \times T \to M(T) \).

Parameters
xsA monadic structure.
prefA value (the prefix) to insert before each element of a monadic structure.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <string>
namespace hana = boost::hana;
using namespace std::literals;
int main() {
hana::prefix(hana::make_tuple("dog"s, "car"s, "house"s), "my"s)
==
hana::make_tuple("my", "dog", "my", "car", "my", "house")
);
}
constexpr auto boost::hana::prepend

#include <boost/hana/fwd/prepend.hpp>

Initial value:
= [](auto&& xs, auto&& x) {
return tag-dispatched;
}

Prepend an element to a monadic structure.Given a monadic structure xs and an element x, prepend returns a new monadic structure which is the result of lifting x into the monadic structure and then combining that (to the left) with xs. In other words,.

prepend(xs, x) == concat(lift<Xs>(x), xs)

For sequences, this has the intuitive behavior of simply prepending an element to the beginning of the sequence, hence the name.

Rationale for not calling this push_front

While push_front is the de-facto name used in the standard library, it also strongly suggests mutation of the underlying sequence, which is not the case here. The author also finds that push_front suggests too strongly the sole interpretation of putting an element to the front of a sequence, whereas prepend is slightly more nuanced and bears its name better for e.g. hana::optional.

Signature

Given a MonadPlus M, the signature is \( \mathtt{prepend} : M(T) \times T \to M(T) \).

Parameters
xsA monadic structure that will be combined to the right of the element.
xAn element to combine to the left of the monadic structure.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
static_assert(hana::prepend(hana::make_tuple(), 1) == hana::make_tuple(1), "");
static_assert(hana::prepend(hana::make_tuple('2', 3.3), 1) == hana::make_tuple(1, '2', 3.3), "");
int main() { }
constexpr auto boost::hana::remove

#include <boost/hana/fwd/remove.hpp>

Initial value:
= [](auto&& xs, auto&& value) {
return tag-dispatched;
}
constexpr auto value
Return the compile-time value associated to a constant.This function returns the value associated to ...
Definition: value.hpp:54

Remove all the elements of a monadic structure that are equal to some value.Given a monadic structure xs and a value, remove returns a new monadic structure equal to xs without all its elements that are equal to the given value. remove is equivalent to remove_if with the equal.to(value) predicate, i.e.

remove(xs, value) == remove_if(xs, equal.to(value))

Signature

Given a MonadPlus M and a value of type T, the signature is \( \mathrm{remove} : M(T) \times T \to M(T) \)

Parameters
xsA monadic structure to remove some elements from.
valueA value that is compared to every element x of the structure. Elements of the structure that are equal to that value are removed from the structure. This requires every element to be Comparable with value. Furthermore, in the current version of the library, comparing value with any element of the structure must yield a compile-time Logical.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
BOOST_HANA_CONSTANT_CHECK(hana::remove(hana::tuple_t<int, char, float>, hana::type_c<char>) == hana::tuple_t<int, float>);
BOOST_HANA_CONSTANT_CHECK(hana::remove(hana::just(hana::type_c<int>), hana::type_c<char>) == hana::just(hana::type_c<int>));
BOOST_HANA_CONSTANT_CHECK(hana::remove(hana::just(hana::type_c<int>), hana::type_c<int>) == hana::nothing);
int main() { }
constexpr auto boost::hana::remove_if

#include <boost/hana/fwd/remove_if.hpp>

Initial value:
= [](auto&& xs, auto&& predicate) {
return tag-dispatched;
}

Remove all the elements of a monadic structure that satisfy some predicate.Given a monadic structure xs and a unary predicate, remove_if returns a new monadic structure equal to xs without all its elements that satisfy the predicate. This is equivalent to filter with a negated predicate, i.e.

remove_if(xs, predicate) == filter(xs, negated predicated)

Signature

Given a MonadPlus M and a predicate of type \( T \to Bool \) for some compile-time Logical Bool, the signature is \( \mathrm{remove\_if} : M(T) \times (T \to Bool) \to M(T) \)

Parameters
xsA monadic structure to remove some elements from.
predicateA unary predicate called as predicate(x), where x is an element of the structure, and returning whether x should be removed from the structure. In the current version of the library, predicate must return a compile-time Logical.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <type_traits>
namespace hana = boost::hana;
// First get the type of the object, and then call the trait on it.
constexpr auto is_integral = hana::compose(hana::trait<std::is_integral>, hana::typeid_);
static_assert(hana::remove_if(hana::make_tuple(1, 2.0, 3, 4.0), is_integral) == hana::make_tuple(2.0, 4.0), "");
static_assert(hana::remove_if(hana::just(3.0), is_integral) == hana::just(3.0), "");
BOOST_HANA_CONSTANT_CHECK(hana::remove_if(hana::just(3), is_integral) == hana::nothing);
int main() { }
template<typename M >
constexpr auto boost::hana::replicate

#include <boost/hana/fwd/replicate.hpp>

Initial value:
= [](auto&& x, auto const& n) {
return tag-dispatched;
}

Create a monadic structure by combining a lifted value with itself n times.Given a value x, a non-negative IntegralConstant n and the tag of a monadic structure M, replicate creates a new monadic structure which is the result of combining x with itself n times inside the monadic structure. In other words, replicate simply lifts x into the monadic structure, and then combines that with itself n times:

replicate<M>(x, n) == cycle(lift<M>(x), n)

If n is zero, then the identity of the concat operation is returned. In the case of sequences, this corresponds to creating a new sequence holding n copies of x.

Signature

Given an IntegralConstant C and MonadPlus M, the signature is \( \mathtt{replicate}_M : T \times C \to M(T) \).

Template Parameters
MThe tag of the returned monadic structure. It must be a model of the MonadPlus concept.
Parameters
xThe value to lift into a monadic structure and then combine with itself.
nA non-negative IntegralConstant representing the number of times to combine lift<M>(x) with itself. If n == 0, replicate returns empty<M>().

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
static_assert(hana::replicate<hana::tuple_tag>('x', hana::size_c<2>) == hana::make_tuple('x', 'x'), "");
// Of course, there can't be more than one element in an `optional`.
static_assert(hana::replicate<hana::optional_tag>('x', hana::size_c<2>) == hana::just('x'), "");
int main() { }
constexpr auto boost::hana::suffix

#include <boost/hana/fwd/suffix.hpp>

Initial value:
= [](auto&& xs, auto&& sfx) {
return tag-dispatched;
}

Inserts a value after each element of a monadic structure.Given a monadic structure xs and a value z (called the suffix), suffix returns a new monadic structure such that.

suffix(xs, z) == flatten(transform(xs, [](auto x) {
return concat(lift<M>(x), lift<M>(z));
}))

For sequences, this simply corresponds to inserting the suffix after each element of the sequence. For example, given a sequence [x1, ..., xn], suffix will return

[x1, z, x2, z, ..., xn, z]

As explained above, this can be generalized to other MonadPlus models, with various levels of interest.

Signature

Given a MonadPlus M, the signature is \( \mathtt{suffix} : M(T) \times T \to M(T) \).

Parameters
xsA monadic structure.
sfxA value (the suffix) to insert after each element of a monadic structure.

Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
static_assert(
hana::suffix(hana::make_tuple(1, 2, 3, 4), 0) == hana::make_tuple(1, 0, 2, 0, 3, 0, 4, 0)
, "");
int main() { }