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; } );
}
}
}