もにゃど

これぐらいなら FC++ あたりを漁ればあるような気がする.っていうかもにゃど分かんね.そこらへんに落ちてた解説をてけとーに読んだ結果,「合成演算に何かを引っ掛ける」ぐらいにしか理解できていない.手続き脳の限界.っていうか手続きで書ける言語にもにゃどがあってうれしいことってあるんでしょうかね.
#うれしい気がしてきた.でもねもい
#あ,下のコード無駄に stdexcept インクルードしてるし.これプラス F の次が G じゃなくて H なところから推論される結論は……「error monad も作ろうとしてたけど何となく途中でやめてしまった」.

#include <iostream>
#include <stdexcept>

#include <boost/optional.hpp>
#include <boost/utility/result_of.hpp>


namespace maybe_monad{

template< class F, class G >
class maybe_combinator
{
public:
  template< class FArgs >
  struct result;

  template< class C, class T >
  struct result< C( T ) >
    : public boost::result_of<
          G( typename boost::result_of<
              F( typename boost::remove_reference< T >::type const & ) >::type::value_type )
        >
  {};

  maybe_combinator( F f, G g )
    : f_( f )
    , g_( g )
  {}

  template< class T >
  typename result< maybe_combinator const( T const & ) >::type
  operator()( T const &x ) const
  {
    typedef typename boost::result_of< F( T const & ) >::type R;
    R y = f_( x );
    if( y ){
      return g_( *y );
    }

    return R();
  }

private:
  F f_;
  G g_;
};

template< class F, class G >
maybe_combinator< F, G >
operator*( F f, G g )
{
  return maybe_combinator< F, G >( f, g );
}

} // namespace maybe_monad



namespace writer_monad{

template< class F, class G >
class writer_combinator
{
public:
  template< class FArgs >
  struct result;

  template< class C, class T >
  struct result< C( T ) >
    : public boost::result_of<
          G const(
              typename boost::result_of<
                  F const( typename boost::remove_reference< T >::type const & )
                >::type ) >
  {};

  writer_combinator( F f, G g )
    : f_( f )
    , g_( g )
  {}

  template< class T >
  typename boost::result_of<
      G const( typename boost::result_of< F const( T const & ) >::type const & )
    >::type
  operator()( T const &x ) const
  {
    typename boost::result_of< F( T const & ) >::type y = f_( x );
    std::cout << y << std::endl;
    return g_( y );
  }

private:
  F f_;
  G g_;
};

template< class F, class G >
writer_combinator< F, G >
operator*( F f, G g )
{
  return writer_combinator< F, G >( f, g );
}

} // namespace writer_combinator



struct F
{
  typedef boost::optional< int > result_type;

  boost::optional< int > operator()( int i ) const
  {
    if( i < 10 ){
      return boost::optional< int >( i * 2 );
    }

    return boost::optional< int >();
  }
};

F const f = F();



struct H
{
  typedef int result_type;

  int operator()( int i ) const
  {
    return i * 2;
  }
};

H const h = H();



int main()
{
  { using namespace maybe_monad;
  boost::optional< int > i = ( f * f * f )( 1 );
  if( i ){
    std::cout << *i << std::endl;
  }
  else{
    std::cout << "Null" << std::endl;
  }
  }

  std::cout << "****************************************" << std::endl;

  { using namespace maybe_monad;
  boost::optional< int > i = ( f * f * f * f * f )( 1 );
  if( i ){
    std::cout << *i << std::endl;
  }
  else{
    std::cout << "Null" << std::endl;
  }
  }

  std::cout << "****************************************" << std::endl;

  { using namespace writer_monad;
  std::cout << ( h * h * h * h * h * h )( 1 ) << std::endl;
  }
}