using System; namespace Test { /* well fuck // class Monad m where public interface Mandadka { // (>>=) :: m a -> (a -> m b) -> m b Mandadka bind( Func Func ); //(>>) :: m a -> m b -> m b // unused // return :: a -> m a // Mandadka wrap( A arg ); // it will be static // fail :: String -> m a // unused }*/ public class MaybeInternal { public enum TYPE { Nothing, Just } public TYPE type { get; private set; } public T value { get; private set; } public MaybeInternal( TYPE t ) { if ( t != TYPE.Nothing ) throw new ArgumentException( "You forgot to pass value to Just constructor" ); type = t; } public MaybeInternal( TYPE t, T value ) { if ( t != TYPE.Just || value == null ) throw new ArgumentException( "shit happened" ); type = t; this.value = value; } } public static class Maybe /*: Mandadka*/ { public static MaybeInternal bind( this MaybeInternal arg, Func func ) where B:class { B tmp = null; if ( arg == null || arg.type == MaybeInternal.TYPE.Nothing ) { return wrap( tmp ); } else { // Just x return wrap( func( arg.value ) ); } } public static MaybeInternal wrap( B arg ) { if ( arg == null ) { return new MaybeInternal( MaybeInternal.TYPE.Nothing ); } else { return new MaybeInternal( MaybeInternal.TYPE.Just, arg ); } } public static bool isNothing( this MaybeInternal a ) { return ( a == null || a.type == MaybeInternal.TYPE.Nothing ); } } // test class public class Person { public string race; public int dickLen; public Person( string race, int dickLen ) { this.race = race; this.dickLen = dickLen; } } class Program { static void Main( string[] args ) { Person first = new Person( "nigra", 20 ); Person second = null; Maybe.wrap( first ) .bind( ( Person x ) => { x.dickLen++; return x; } ) .bind( ( Person x ) => { x.race += "!"; return x; } ) .bind( ( Person x ) => { Console.WriteLine( "{0} {1}", x.race, x.dickLen ); return x; } ); Maybe.wrap( second ) .bind( ( Person x ) => { x.dickLen++; return x; } ) .bind( ( Person x ) => { x.race += "!"; return x; } ) .bind( ( Person x ) => { Console.WriteLine( "{0} {1}", x.race, x.dickLen ); return x; } ); } } }