using System;
namespace Test {
/* well
fuck
// class Monad m where
public interface Mandadka {
// (>>=) :: m a -> (a -> m b) -> m b
Mandadka bind<A, B>( Func<A, B> Func );
//(>>) :: m a -> m b -> m b
// unused
// return :: a -> m a
// Mandadka wrap<A>( A arg ); // it will be static
// fail :: String -> m a
// unused
}*/
public class MaybeInternal<T> {
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<B> bind<T, B>( this MaybeInternal<T> arg, Func<T, B> func ) where B:class {
B tmp = null;
if ( arg == null || arg.type == MaybeInternal<T>.TYPE.Nothing ) {
return wrap<B>( tmp );
} else { // Just x
return wrap<B>( func( arg.value ) );
}
}
public static MaybeInternal<B> wrap<B>( B arg ) {
if ( arg == null ) {
return new MaybeInternal<B>( MaybeInternal<B>.TYPE.Nothing );
} else {
return new MaybeInternal<B>( MaybeInternal<B>.TYPE.Just, arg );
}
}
public static bool isNothing<T>( this MaybeInternal<T> a ) {
return ( a == null || a.type == MaybeInternal<T>.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; } );
}
}
}