#include <cstdio>
template<class T>
struct maybe
{
maybe( const T& t ) : argument( t ), valid( true ) {}
maybe() : argument(), valid( false ) {}
T argument;
bool valid;
};
template<class T>
maybe<T> just( const T& t ) { return maybe<T>(t); }
template<class T>
maybe<T> nothing() { return maybe<T>(); }
auto terminal_maybe = [] ( auto term ) {
return [=] ( auto func ) {
return func( term );
};
};
auto fmap_maybe = [] ( auto f ) {
return [=] ( auto t ) {
if( t.valid ) {
try {
t.argument = f( t.argument );
printf("argument = %d\n",t.argument);
}
catch(...) {
t.valid = false;
}
}
return (t.valid) ? terminal_maybe( just( t.argument ) ) : terminal_maybe( nothing<decltype(t.argument)>() );
};
};
int main( int argc, char* argv[] )
{
auto plus_2 = [] ( auto arg ) { return arg + 2; };
auto minus_2 = [] ( auto arg ) { return arg - 2; };
maybe<int> forty = just(40);
auto result = terminal_maybe(forty)
(fmap_maybe( plus_2 ))
(fmap_maybe( plus_2 ));
result([] (maybe<int> m) {
if(m.valid) {
printf("results = %d\n", m.argument);
} else {
printf("results = invalid\n");
}
} );
return 0;
}
I2luY2x1ZGUgPGNzdGRpbz4KCnRlbXBsYXRlPGNsYXNzIFQ+CnN0cnVjdCBtYXliZQp7CiAgICBtYXliZSggY29uc3QgVCYgdCApIDogYXJndW1lbnQoIHQgKSwgdmFsaWQoIHRydWUgKSB7fQogICAgbWF5YmUoKSA6IGFyZ3VtZW50KCksIHZhbGlkKCBmYWxzZSApIHt9CgogICAgVCBhcmd1bWVudDsKICAgIGJvb2wgdmFsaWQ7Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBUPgptYXliZTxUPiBqdXN0KCBjb25zdCBUJiB0ICkgeyByZXR1cm4gbWF5YmU8VD4odCk7IH0KCnRlbXBsYXRlPGNsYXNzIFQ+Cm1heWJlPFQ+IG5vdGhpbmcoKSB7IHJldHVybiBtYXliZTxUPigpOyB9CgphdXRvIHRlcm1pbmFsX21heWJlID0gW10gKCBhdXRvIHRlcm0gKSB7CiAgICByZXR1cm4gWz1dICggYXV0byBmdW5jICkgewogICAgICAgIHJldHVybiBmdW5jKCB0ZXJtICk7CiAgICB9Owp9OwoKYXV0byBmbWFwX21heWJlID0gW10gKCBhdXRvIGYgKSB7CiAgICByZXR1cm4gWz1dICggYXV0byB0ICkgewogICAgICAgIGlmKCB0LnZhbGlkICkgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgdC5hcmd1bWVudCA9IGYoIHQuYXJndW1lbnQgKTsKICAgICAgICAgICAgICAgIHByaW50ZigiYXJndW1lbnQgPSAlZFxuIix0LmFyZ3VtZW50KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjYXRjaCguLi4pIHsKICAgICAgICAgICAgICAgIHQudmFsaWQgPSBmYWxzZTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgcmV0dXJuICh0LnZhbGlkKSA/IHRlcm1pbmFsX21heWJlKCBqdXN0KCB0LmFyZ3VtZW50ICkgKSA6IHRlcm1pbmFsX21heWJlKCBub3RoaW5nPGRlY2x0eXBlKHQuYXJndW1lbnQpPigpICk7CiAgICB9Owp9OwoKaW50IG1haW4oIGludCBhcmdjLCBjaGFyKiBhcmd2W10gKQp7CiAgICBhdXRvIHBsdXNfMiA9IFtdICggYXV0byBhcmcgKSB7IHJldHVybiBhcmcgKyAyOyB9OwogICAgYXV0byBtaW51c18yID0gW10gKCBhdXRvIGFyZyApIHsgcmV0dXJuIGFyZyAtIDI7IH07CgogICAgbWF5YmU8aW50PiBmb3J0eSA9IGp1c3QoNDApOwoKICAgIGF1dG8gcmVzdWx0ID0gdGVybWluYWxfbWF5YmUoZm9ydHkpCiAgICAgICAgKGZtYXBfbWF5YmUoIHBsdXNfMiApKQogICAgICAgIChmbWFwX21heWJlKCBwbHVzXzIgKSk7CgogICAgcmVzdWx0KFtdIChtYXliZTxpbnQ+IG0pIHsgCiAgICAJaWYobS52YWxpZCkgewoJCQlwcmludGYoInJlc3VsdHMgPSAlZFxuIiwgbS5hcmd1bWVudCk7ICAgCQkKICAgIAl9IGVsc2UgewogICAgCQlwcmludGYoInJlc3VsdHMgPSBpbnZhbGlkXG4iKTsJCiAgICAJfQogICAgfSApOwoKICAgIHJldHVybiAwOwp9