Boost.Hana: Applicative

| Boost.Hana 1.4.0 Your standard library for metaprogramming |

Variables
Applicative
Concepts

## Description

The `Applicative` concept represents `Functor`s with the ability to lift values and combine computations.

A `Functor` can only take a normal function and map it over a structure containing values to obtain a new structure containing values. Intuitively, an `Applicative` can also take a value and lift it into the structure. In addition, an `Applicative` can take a structure containing functions and apply it to a structure containing values to obtain a new structure containing values. By currying the function(s) inside the structure, it is then also possible to apply n-ary functions to n structures containing values.

Note
  This documentation does not go into much details about the nature of applicatives. However, the Typeclassopedia is a nice Haskell-oriented resource where such information can be found.

## Minimal complete definition

`lift` and `ap` satisfying the laws below. An `Applicative` must also be a `Functor`.

## Laws

Given an `Applicative` `F`, the following laws must be satisfied:

1. Identity
   For all objects `xs` of tag `F(A)`,
   ap(lift<F>(id), xs) == xs
2. Composition
   For all objects `xs` of tag `F(A)` and functions-in-an-applicative \( fs : F(B \to C) \), \( gs : F(A \to B) \),
   ap(ap(lift<F>(compose), fs, gs), xs) == ap(fs, ap(gs, xs))
3. Homomorphism
   For all objects `x` of tag `A` and functions \( f : A \to B \),
   ap(lift<F>(f), lift<F>(x)) == lift<F>(f(x))
4. Interchange
   For all objects `x` of tag `A` and functions-in-an-applicative \( fs : F(A \to B) \),
   ap(fs, lift<F>(x)) == ap(lift<F>(apply(-, x)), fs)
   where `apply(-, x)` denotes the partial application of the `apply` function from the Functional module to the `x` argument.

As a consequence of these laws, the model of `Functor` for `F` will satisfy the following for all objects `xs` of tag `F(A)` and functions \( f : A \to B \):

transform(xs, f) == ap(lift<F>(f), xs)

## Refined concept

1. `Functor` (free model)
   As a consequence of the laws, any `Applicative F` can be made a `Functor` by setting
   transform(xs, f) = ap(lift<F>(f), xs)

## Concrete models

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

## Structure-preserving functions

An applicative transformation is a function \( t : F(X) \to G(X) \) between two Applicatives `F` and `G`, where `X` can be any tag, and which preserves the operations of an Applicative. In other words, for all objects `x` of tag `X`, functions-in-an-applicative \( fs : F(X \to Y) \) and objects `xs` of tag `F(X)`,

t(lift<F>(x)) == lift<G>(x)
t(ap(fs, xs)) == ap(t(fs), t(xs))

## Variables
constexpr auto | boost::hana::ap
| Lifted application.Specifically, `ap` applies a structure containing functions to a structure containing values, and returns a new structure containing values. The exact way in which the functions are applied to the values depends on the `Applicative`. More...
template<typename A >
constexpr auto | boost::hana::lift
| Lift a value into an `Applicative` structure.`lift<A>` takes a normal value and embeds it into a structure whose shape is represented by the `A` `Applicative`. Note that the value may be a function, in which case the created structure may be `ap`plied to another `Applicative` structure containing values. More...

## Variable Documentation

constexpr auto boost::hana::ap

`#include <boost/hana/fwd/ap.hpp>`

Initial value:
= [](auto&& f, auto&& ...x) -> decltype(auto) {
return tag-dispatched;
}

Lifted application.Specifically, `ap` applies a structure containing functions to a structure containing values, and returns a new structure containing values. The exact way in which the functions are applied to the values depends on the `Applicative`.

`ap` can be called with two arguments or more; the functions in the `f` structure are curried and then applied to the values in each `x...` structure using the binary form of `ap`. Note that this requires the number of `x...` must match the arity of the functions in the `f` structure. In other words, `ap(f, x1, ..., xN)` is equivalent to

((f' <ap> x1) <ap> x2) ... <ap> xN

where `f'` is `f` but containing curried functions instead and `x <ap> y` is just `ap(x, y)` written in infix notation to emphasize the left associativity.

## Signature

Given an Applicative `A`, the signature is \( \mathtt{ap} : A(T_1 \times \cdots \times T_n \to U) \times A(T_1) \times \cdots \times A(T_n) \to A(U) \).

Parameters

  f | A structure containing function(s).
  x... | Structure(s) containing value(s) and on which `f` is applied. The number of structures must match the arity of the functions in the `f` 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 <boost/hana/ap.hpp>
#include <boost/hana/assert.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/optional.hpp>
#include <boost/hana/tuple.hpp>
#include <functional>
namespace hana = boost::hana;
int main() {
// with tuples
static_assert(
hana::ap(hana::make_tuple(std::plus<>{}), hana::make_tuple(1, 2),
hana::make_tuple(3, 4, 5))
==
hana::make_tuple(
1 + 3, 1 + 4, 1 + 5,
2 + 3, 2 + 4, 2 + 5
)
, "");
// with optional values
BOOST_HANA_CONSTEXPR_LAMBDA auto multiply = [](auto a, auto b, auto c) {
return a * b * c;
};
BOOST_HANA_CONSTEXPR_CHECK(
hana::ap(hana::just(multiply), hana::just(1),
hana::just(2),
hana::just(3))
==
hana::just(1 * 2 * 3)
);
BOOST_HANA_CONSTANT_CHECK(
hana::ap(hana::just(multiply), hana::just(1),
hana::nothing,
hana::just(3))
==
hana::nothing
);
}

Todo:
  Consider giving access to all the arguments to the tag-dispatched implementation for performance purposes.

template<typename A >

constexpr auto boost::hana::lift

`#include <boost/hana/fwd/lift.hpp>`

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

Lift a value into an `Applicative` structure.`lift<A>` takes a normal value and embeds it into a structure whose shape is represented by the `A` `Applicative`. Note that the value may be a function, in which case the created structure may be `ap`plied to another `Applicative` structure containing values.

## Signature

Given an Applicative `A`, the signature is \( \mathtt{lift}_A : T \to A(T) \).

Template Parameters

  A | A tag representing the `Applicative` into which the value is lifted.

Parameters

  x | The value to lift into the applicative.

## 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 <boost/hana/equal.hpp>
#include <boost/hana/lift.hpp>
#include <boost/hana/optional.hpp>
#include <boost/hana/tuple.hpp>
namespace hana = boost::hana;
static_assert(hana::lift<hana::tuple_tag>('x') == hana::make_tuple('x'), "");
static_assert(hana::lift<hana::optional_tag>('x') == hana::just('x'), "");
int main() { }