Functional Programming in C++

后端 未结 6 501
隐瞒了意图╮
隐瞒了意图╮ 2021-01-30 10:41

Can someone guide me how do functional programming in C++? Is there some good online material that I can refer?

Please note that I know about the library FC++. I want to

6条回答
  •  無奈伤痛
    2021-01-30 11:04

    UPD Dec 2018

    I've created a comprehensive list of materials where you can find articles, talks, screencasts, papers, libraries and showcases:

    Functional Programming in C++


    Consider my 4 research projects:

    • Functional and Declarative Design in C++. (GitHub) (Slides (Rus)) (Talk (Rus))

    This project is a working prototype of 'Amber' game. The code demonstrates many of major functional concepts: immutability, lambdas, monads, combinators, pure functions, declarative code design. It uses Qt C++ and C++11 features.

    For a quick example, see how tasks can be chained into one big task that will modify the Amber's world when it's applied:

    const AmberTask tickOneAmberHour = [](const amber::Amber& amber)
    {
        auto action1Res = magic::anyway(inflateShadowStorms, magic::wrap(amber));
        auto action2Res = magic::anyway(affectShadowStorms, action1Res);
        auto action3Res = magic::onFail(shadowStabilization, action2Res);
        auto action4Res = magic::anyway(tickWorldTime, action3Res);
        return action4Res.amber;
    };
    
    • Lenses in C++. (GitHub) (Slides (Eng)) (Talk (Rus))

    This is a showcase of generic functional lenses in C++. The implementatoin is built with using of Variadic Templates, some intresting (and valid) C++ hacks to make lenses composable and neat-looking. The library is just a demo for the talk and thus it provides only a few of most important combinators, namely: set(), view(), traverse(), bind(), infix literal combinator to, over() and other.

    (Note that there exist the 'C++ Lenses' project: but it's not about real 'lenses', it's about class properties with getters and setters in sense of C# or Java properties.)

    Quick example

    Car car1 = {"x555xx", "Ford Focus", 0, {}};
    Car car2 = {"y555yy", "Toyota Corolla", 10000, {}};
    
    std::vector cars = {car1, car2};
    
    auto zoomer = traversed() to modelL();
    
    std::function variator = [](std::string) { return std::string("BMW x6"); };
    std::vector result = over(zoomer, cars, variator);
    
    QVERIFY(result.size() == 2);
    QVERIFY(result[0].model == "BMW x6");
    QVERIFY(result[1].model == "BMW x6");
    
    • Functional 'Life': parallel celullar automata and comonads. (GitHub) (Slides (Eng)) (Talk (Rus))

    You have probably heard about monads. Monads are everywhere in talks about functional programming now. It's a buzzword. But what about comonads? I presented 1D and 2D celullar automata with the concept of comonads under the hood. The aim was to show how easy it is to move from the single-flow code to the parallel one using std::future as a Par monad. The project also benchmarks and compares two these approaches.

    Quick example

    template 
    UUB fmap(
        const func& f,
        const UUUUA& uuu)
    {
        const func f2 = [=](const UUUA& uuu2)
        {
            UB newUt;
            newUt.position = uuu2.position;
            newUt.field = fp::map(f, uuu2.field);
            return newUt;
        };
    
        return { fp::map(f2, uuu.field), uuu.position };
    }
    
    • Pure functional Software Transactional Memory (STM) library that is called cpp_stm_free. (GitHub) (Slides (Eng)) (Talk (Rus)) (Tutorial (Eng)) (Dining Philosopher sample).

    This library is based on Free monad and some other advanced ideas of Functional Programming. Its interface is similar to Haskell's native STM library. Transactions are monadically composable, pure functional, and there is a lot of useful monadic combinators to make designing of concurrent model more convenient and powerful. I've implemented the Dining Philosophers problem using the library, and it works well. Here is a sample of some transaction for taking of forks by a philosopher:

    STML takeFork(const TFork& tFork) {
        return withTVar(tFork, [=](const Fork& fork) {
           if (fork.state == ForkState::Free) {
               return writeTVar(tFork, Fork {fork.name, ForkState:Taken});
           }
           else {
               return retry();
           }
        });
    }
    
    STML takeForks(const TForkPair& forks) {
        STML lm = takeFork(forks.left);
        STML rm = takeFork(forks.right);
        return sequence(lm, rm);
    }
    

提交回复
热议问题