Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Has this been done before? (Monad view wrapping c++ collections/types for chain operations)

I was writing some scala at home for fun the other night and thought myself, "wouldn't it be cool if we had this kind of API in C++? - Is it possible?". I started searching for c++, monads and stl collections, but couldn't find anything that seemed to actually increase my productivity :/.

So I set out to implement some proof-of-concept (super inefficient, but at least it works! :)) for what's normally seen in more dedicated functional languages.

auto m = monadic(std::vector<int>{1,2,3});
auto mMapped = m.map([](int x) {return x*x; });

Monadic<std::vector<int>> mFiltered = m.filter([](int x) {return x > 1; });

std::vector<std::string> funList = 
    monadic(src)
        .flatMap([](int x) { return std::vector<int>{1,2,3};} )
        .filter([](int x) { return x > 1; })
        .map([](int x) { return std::to_string(x).append("_string"); })
        .col;

I would really like such a library (but more complete and efficient using move semantics) for my every day c++ code (data management, threading and distributed execution becomes so easy).

The question: --> Do you know of any such library for C++11 or C++14? <--

The code above was using a very quickly hacked together PoC library I put here https://github.com/GiGurra/cpp_monad (Tested it ok with gcc 4.9.2, VS2015 and some version of clang, can't remember).

The "Monadic" class doesn't contain any specific implementation, it just passes on to whatever map/filter/flatMap free functions are available for the given collection type, for example the map operation is very naively implemented like:

class Monadic {
public:
    ...
    template <typename MapFcn> 
    auto map(MapFcn mapFcn) { return monadic(cpp_monad::map(col, mapFcn)); }
    ...
};

// Default naive implementation in unspecialized case
template <typename T_Coll, typename T_MapFcn>
auto map(const T_Coll& src, T_MapFcn fcn) {
    std::vector<decltype(fcn(internal::_firstElem(src)))> out;
    std::transform(std::begin(src), std::end(src), std::back_inserter(out), fcn);
    return out;
};

This way you could replace either the wrapper or the implementation without having to modify the code using the particular API.

Just an idea, perhaps there's something already out there but a lot better.

like image 763
user1892422 Avatar asked Feb 02 '15 19:02

user1892422


1 Answers

Take a look at Eric Niebler's Ranges proposal and sample implementation for a similar API that's been proposed for a future C++ standard.

Chandler Carruth's C++Now 2014 talk on Range algorithms is about another attempt to design a more 'functional' style algorithms library for C++.

like image 53
mattnewport Avatar answered Oct 14 '22 08:10

mattnewport