In Haskell, one can write something like

*f . g*, meaning the composition of

*f*and

*g*. It produces a function,

*h*, such that

*h(x) = f( g(x) )*. Since Haskell uses curried notation, if

*f*takes two arguments, then

*h*would be defined

*h(x,y) = f( g(x), y )*. Composition becomes especially useful when we can express a chain of function calls with it. For example this...

*auto y = f(x);*

*auto z = g(y);*

*auto a = h(z);*

...could be rewritten like so, using Haskell notation:

*auto a = (h . g . f)(x);*

As with partial application, one might first think of writing

*compose*as a lambda function, but we don't know the type of the arguments. Instead, we create a type that holds f and g.

*template< class F, class G > struct Composition {*

*F f;*

*G g;*

*template< class _F, class _G >*

*constexpr Composition( _F&& f, _G&& g ) : f( forward<_F>(f) ), g( forward<_G>(g) ) { }*

*template< class X, class ...Y >*

*decltype( f( g(declval<X>()), declval<Y>()... ) )*

*operator() ( X&& x, Y&& ...y ) {*

*return f( g(forward<X>(x)), forward<Y>(y)... );*

*}*

*};*

*template< class F, class G, class C = Composition<F,G> >*

*constexpr C compose( F f, G g ) {*

*return C( move(f), move(g) );*

*}*

We can now very simply define a:

Composition really doesn't get more complicated than that. We can implement a few different versions for slightly different purposes, but that's about it. Still, this adds flexibility, so let's look at some others. Each requires writing its own

First, i should note that the GCC extends the standard by adding

Our regular

At the end of the day, if a composition does not exists that perfectly meats one's needs, it can be trivially implemented.

*auto a = compose( h, compose(g,f) )(x);**auto b = compose( compose(h,g) f )(x); // Equivalently*Composition really doesn't get more complicated than that. We can implement a few different versions for slightly different purposes, but that's about it. Still, this adds flexibility, so let's look at some others. Each requires writing its own

*Composition*class, but i'll just briefly go over the different ways to look at compositions.First, i should note that the GCC extends the standard by adding

*compose1*and*compose2*.*compose1*acts on unary functions (like*f(x)*), however it is unlike the the above*compose*in that it expects*f*to take only one argument (the return of*g(x)*).*compose2*does something more interesting. Consider this:*typedef std::pair<int,int> vec;**int& vec_x( vec& v ) { return v.first; }**int& vec_y( vec& v ) { return v.second; }*

*auto sum_of_elements = __gnu_cxx::compose2( std::plus<int>(), vec_x, vec_y );**int five = sum_of_elements( std::make_pair(2,3) );**compose2*takes one binary function (in this case,*+*), and two unary functions and produces a unary function.*sum_of_elements(v) = vec_x(v) + vec_y(v)*. This is not standard, however, so implementing our own version makes sense for portability. I might rename this function to*bcompose*for "binary composition".Our regular

*compose*function expects a n-ary*f*and a unary*g*. Wouldn't a version expecting a unary*f*and n-ary*g*be helpful? I would call this*mcompose*.At the end of the day, if a composition does not exists that perfectly meats one's needs, it can be trivially implemented.

## No comments:

## Post a Comment

Please feel free to post any comments, concerns, questions, thoughts and ideas. I am perhaps more interested in what you have to say than you are in what I do.