Boost.Hana  1.0.2
Your standard library for metaprogramming
Functor

Description

The Functor concept represents types that can be mapped over.

Intuitively, a Functor is some kind of box that can hold generic data and map a function over this data to create a new, transformed box. Because we are only interested in mapping a function over the contents of a black box, the only real requirement for being a functor is to provide a function which can do the mapping, along with a couple of guarantees that the mapping is well-behaved. Those requirements are made precise in the laws below. The pattern captured by Functor is very general, which makes it widely useful. A lot of objects can be made Functors in one way or another, the most obvious example being sequences with the usual mapping of the function on each element. While this documentation will not go into much more details about the nature of functors, the Typeclassopedia is a nice Haskell-oriented resource for such information.

Functors are parametric data types which are parameterized over the data type of the objects they contain. Like everywhere else in Hana, this parametricity is only at the documentation level and it is not enforced.

In this library, the mapping function is called transform after the std::transform algorithm, but other programming languages have given it different names (usually map).

Note
The word functor comes from functional programming, where the concept has been used for a while, notably in the Haskell programming language. Haskell people borrowed the term from category theory, which, broadly speaking, is a field of mathematics dealing with abstract structures and transformations between those structures.

Minimal complete definitions

  1. transform
    When transform is specified, adjust_if is defined analogously to
    adjust_if(xs, pred, f) = transform(xs, [](x){
    if pred(x) then f(x) else x
    })
  2. adjust_if
    When adjust_if is specified, transform is defined analogously to
    transform(xs, f) = adjust_if(xs, always(true), f)

Laws

Let xs be a Functor with tag F(A), \( f : A \to B \) and \( g : B \to C \). The following laws must be satisfied:

transform(xs, id) == xs
transform(xs, compose(g, f)) == transform(transform(xs, f), g)

The first line says that mapping the identity function should not do anything, which precludes the functor from doing something nasty behind the scenes. The second line states that mapping the composition of two functions is the same as mapping the first function, and then the second on the result. While the usual functor laws are usually restricted to the above, this library includes other convenience methods and they should satisfy the following equations. Let xs be a Functor with tag F(A), \( f : A \to A \), \( \mathrm{pred} : A \to \mathrm{Bool} \) for some Logical Bool, and oldval, newval, value objects of tag A. Then,

adjust(xs, value, f) == adjust_if(xs, equal.to(value), f)
adjust_if(xs, pred, f) == transform(xs, [](x){
if pred(x) then f(x) else x
})
replace_if(xs, pred, value) == adjust_if(xs, pred, always(value))
replace(xs, oldval, newval) == replace_if(xs, equal.to(oldval), newval)
fill(xs, value) == replace_if(xs, always(true), value)

The default definition of the methods will satisfy these equations.

Concrete models

hana::lazy, hana::optional, hana::tuple

Structure-preserving functions for Functors

A mapping between two functors which also preserves the functor laws is called a natural transformation (the term comes from category theory). A natural transformation is a function f from a functor F to a functor G such that for every other function g with an appropriate signature and for every object xs of tag F(X),

f(transform(xs, g)) == transform(f(xs), g)

There are several examples of such transformations, like to<tuple_tag> when applied to an optional value. Indeed, for any function g and hana::optional opt,

to<tuple_tag>(transform(opt, g)) == transform(to<tuple_tag>(opt), g)

Of course, natural transformations are not limited to the to<...> functions. However, note that any conversion function between Functors should be natural for the behavior of the conversion to be intuitive.

Variables

constexpr auto boost::hana::adjust
 Apply a function on all the elements of a structure that compare equal to some value. More...
 
constexpr auto boost::hana::adjust_if
 Apply a function on all the elements of a structure satisfying a predicate.Given a Functor, a predicate pred and a function f, adjust_if will adjust the elements of the Functor that satisfy the predicate with the function f. In other words, adjust_if will return a new Functor equal to the original one, except that the elements satisfying the predicate will be transformed with the given function. Elements for which the predicate is not satisfied are left untouched, and they are kept as-is in the resulting Functor. More...
 
constexpr auto boost::hana::fill
 Replace all the elements of a structure with a fixed value. More...
 
constexpr auto boost::hana::replace
 Replace all the elements of a structure that compare equal to some value with some new fixed value. More...
 
constexpr auto boost::hana::replace_if
 Replace all the elements of a structure satisfying a predicate with a fixed value. More...
 
constexpr auto boost::hana::transform
 Map a function over a Functor. More...
 

Variable Documentation

constexpr auto boost::hana::adjust

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

Initial value:
= [](auto&& xs, auto&& value, auto&& f) {
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

Apply a function on all the elements of a structure that compare equal to some value.

Signature

Given F a Functor and U a type that can be compared with T's, the signature is \( \mathtt{adjust} : F(T) \times U \times (T \to T) \to F(T) \)

Parameters
xsThe structure to adjust with f.
valueAn object that is compared with each element x of the structure. Elements of the structure that compare equal to value are adjusted with the f function.
fA function called as f(x) on the element(s) of the structure that compare equal to value.

Example

// Copyright Louis Dionne 2013-2016
// 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_CONSTEXPR_LAMBDA auto negate = [](auto x) {
return -x;
};
int main() {
hana::adjust(hana::make_tuple(1, 4, 9, 2, 3, 4), 4, negate)
==
hana::make_tuple(1, -4, 9, 2, 3, -4)
);
}
constexpr auto boost::hana::adjust_if

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

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

Apply a function on all the elements of a structure satisfying a predicate.Given a Functor, a predicate pred and a function f, adjust_if will adjust the elements of the Functor that satisfy the predicate with the function f. In other words, adjust_if will return a new Functor equal to the original one, except that the elements satisfying the predicate will be transformed with the given function. Elements for which the predicate is not satisfied are left untouched, and they are kept as-is in the resulting Functor.

Signature

Given a Functor F and a Logical Bool, the signature is \( \mathtt{adjust_if} : F(T) \times (T \to Bool) \times (T \to T) \to F(T) \)

Parameters
xsThe structure to adjust with f.
predA function called as pred(x) for each element of the Functor, and returning whether f should be applied on that element.
fA function called as f(x) on the element(s) of the Functor that satisfy the predicate.

Example

// Copyright Louis Dionne 2013-2016
// 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_CONSTEXPR_LAMBDA auto negative = [](auto x) {
return x < 0;
};
BOOST_HANA_CONSTEXPR_LAMBDA auto negate = [](auto x) {
return -x;
};
int main() {
hana::adjust_if(hana::make_tuple(-3, -2, -1, 0, 1, 2, 3), negative, negate)
==
hana::make_tuple(3, 2, 1, 0, 1, 2, 3)
);
}
constexpr auto boost::hana::fill

#include <boost/hana/fwd/fill.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

Replace all the elements of a structure with a fixed value.

Signature

Given F a Functor, the signature is \( \mathtt{fill} : F(T) \times U \to F(U) \)

Parameters
xsThe structure to fill with a value.
valueA value by which every element x of the structure is replaced, unconditionally.

Example

// Copyright Louis Dionne 2013-2016
// 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;
int main() {
static_assert(
hana::fill(hana::make_tuple(1, '2', 3.3, nullptr), 'x')
==
hana::make_tuple('x', 'x', 'x', 'x')
, "");
BOOST_HANA_CONSTANT_CHECK(hana::fill(hana::nothing, 'x') == hana::nothing);
static_assert(hana::fill(hana::just('y'), 'x') == hana::just('x'), "");
}
constexpr auto boost::hana::replace

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

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

Replace all the elements of a structure that compare equal to some value with some new fixed value.

Signature

Given F a Functor and U a type that can be compared with T, the signature is \( \mathtt{replace} : F(T) \times U \times T \to F(T) \)

Parameters
xsThe structure to replace elements of.
oldvalAn object compared with each element of the structure. Elements of the structure that compare equal to oldval are replaced by newval in the new structure.
newvalA value by which every element x of the structure that compares equal to oldval is replaced.

Example

// Copyright Louis Dionne 2013-2016
// 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::replace(hana::make_tuple(1, 1, 1, 2, 3, 1, 4, 5), 1, 0)
==
hana::make_tuple(0, 0, 0, 2, 3, 0, 4, 5)
, "");
int main() { }
constexpr auto boost::hana::replace_if

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

Initial value:
= [](auto&& xs, auto&& predicate, 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

Replace all the elements of a structure satisfying a predicate with a fixed value.

Signature

Given F a Functor and Bool a Logical, the signature is \( \mathtt{replace_if} : F(T) \times (T \to Bool) \times T \to F(T) \)

Parameters
xsThe structure to replace elements of.
predicateA function called as predicate(x) for element(s) x of the structure and returning a Logical representing whether x should be replaced by value.
valueA value by which every element x of the structure for which predicate returns a true-valued Logical is replaced.

Example

// Copyright Louis Dionne 2013-2016
// 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_CONSTEXPR_LAMBDA auto negative = [](auto x) {
return x < 0;
};
int main() {
hana::replace_if(hana::make_tuple(-3, -2, -1, 0, 1, 2, 3), negative, 0)
==
hana::make_tuple(0, 0, 0, 0, 1, 2, 3)
);
}
constexpr auto boost::hana::transform

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

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

Map a function over a Functor.

Signature

Given F a Functor, the signature is \( \mathtt{transform} : F(T) \times (T \to U) \to F(U) \)

Parameters
xsThe structure to map f over.
fA function called as f(x) on element(s) x of the structure, and returning a new value to replace x in the structure.

Example

// Copyright Louis Dionne 2013-2016
// 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 <sstream>
#include <string>
#include <type_traits>
namespace hana = boost::hana;
using namespace std::literals;
auto to_string = [](auto x) {
std::ostringstream ss;
ss << x;
return ss.str();
};
int main() {
hana::transform(hana::make_tuple(1, '2', "345", std::string{"67"}), to_string)
==
hana::make_tuple("1", "2", "345", "67")
);
BOOST_HANA_CONSTANT_CHECK(hana::transform(hana::nothing, to_string) == hana::nothing);
BOOST_HANA_RUNTIME_CHECK(hana::transform(hana::just(123), to_string) == hana::just("123"s));
hana::transform(hana::tuple_t<void, int(), char[10]>, hana::template_<std::add_pointer_t>)
==
hana::tuple_t<void*, int(*)(), char(*)[10]>
);
}