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 Functor
s 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
).
transform
transform
is specified, adjust_if
is defined analogously to adjust_if
adjust_if
is specified, transform
is defined analogously to Let xs
be a Functor with tag F(A)
, \( f : A \to B \) and \( g : B \to C \). The following laws must be satisfied:
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,
The default definition of the methods will satisfy these equations.
hana::lazy
, hana::optional
, hana::tuple
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)
,
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
,
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.