PStade.Egg.Monad で遊んでみた

Undocumented ですが,pstade/egg/monad/ 以下に Monad クラスと boost::optional をそのインスタンスとしたものがあります.実用向きとは言えませんが,ちょっと遊んでみました.
monad_optional_test.cpp

#define BOOST_RESULT_OF_USE_DECLTYPE
#include <cmath>
#include <iostream>
#include <boost/optional/optional.hpp>
#include <boost/optional/optional_io.hpp>
#include <pstade/egg/infix.hpp>
#include <pstade/egg/monad/optional.hpp>

int main()
{
    using namespace pstade::egg;
    using namespace pstade::egg::infix;

    std::cout << (

        // return 25 >>=
        monad_return(25.0) ^monad_bind^

        // \d -> if d >= 0 then Just (sqrt d) else Nothing
        [](double d) { return d >= 0.0 ? boost::make_optional(std::sqrt(d)) : boost::none; }

    ) << '\n';
}

出力

5.0

ラムダ式のおかげで,意外にも自然なコードになっています.
調子に乗って,State モナドも実装してみました.
monad_state/core.hpp
https://gist.github.com/1086314
monad_state/state.hpp
https://gist.github.com/1086318
monad_state_state_test.cpp

#define BOOST_RESULT_OF_USE_DECLTYPE
#include <iostream>
#include <pstade/egg/infix.hpp>
#include <pstade/egg/monad/core.hpp>
#include "./monad_state/state.hpp"

int main()
{
    using namespace pstade::egg;
    using namespace pstade::egg::infix;

    auto const v = (

        // return 12 >>
        monad_return(12) ^monad_bind_^ (

        // get >>= \s ->
        X_monad_state_get<state<int, int>> {} () ^monad_bind^ [](int s) { return

        // put (s + 1) >>
        monad_state_put(s + 1) ^monad_bind_^

        // return s
        X_monad_return<state<int, int>>()(s); })

    ).run_state(11);

    std::cout << "(" << v.first << "," << v.second << ")\n";
}

出力

(11,12)

型を明示しなければならない場所が多くて,美しくありませんね.
Expression Template の方が,型推論を上手く扱えそうです.

おまけ

Functor クラス
functor/core.hpp
https://gist.github.com/1086338
functor/optional.hpp
https://gist.github.com/1086340
functor_optional_test.cpp

#include <iostream>
#include <boost/lambda/lambda.hpp>
#include <boost/optional/optional.hpp>
#include <boost/optional/optional_io.hpp>
#include "./functor/optional.hpp"

int main()
{
    using namespace boost::lambda;

    std::cout <<

        // fmap (\x -> x * x) (Just 5.0)
        functor_fmap(_1 * _1, boost::make_optional(5.0))
        
    << '\n' <<

        // fmap (\x -> x * x) (Nothing :: Maybe Double)
        functor_fmap(_1 * _1, boost::optional<double>())

    << '\n';
}