public static void Main() {
var maybe = Maybe<int>.From(10);
var maybe2 = Bind(maybe, a => Maybe<string>.From(a.ToString()));
static IMonad<K, B> Bind<T, K, A, B>(IMonad<T, A> monad, Func<A, IMonad<K, B>> binder) {
return monad.Bind(binder);
abstract class AbstractMonad<T, A> : IMonad<T, A>
public abstract IMonad<K, B> Bind<K, B>(Func<A, IMonad<K, B>> binder);
public abstract IMonad<T, A> Return(A a);
class Maybe<A> : AbstractMonad<Maybe<A>, A>
public static Maybe<A> From(A a) {
public override IMonad<K, B> Bind<K, B>(Func<A, IMonad<K, B>> binder) {
public override IMonad<Maybe<A>, A> Return(A a) {
IMonad<K, B> Bind<K, B>(Func<A, IMonad<K, B>> binder);
IMonad<T, A> Return(A a);