public override Monad <C> Com <B, C>(Func <A, B, C> function, Monad <B> mOther) { Monad <C> resultMonad = new Nothing <C>(); // New Nothing<B> maybe if (!isNothing && !(mOther is Nothing <B>)) { foreach (var otherValue in mOther) { resultMonad = new Just <C>(function(aValue, otherValue)); } } return(resultMonad); }
public override Monad <B> App <B>(Monad <Func <A, B> > functionMonad) { Maybe <B> result = new Nothing <B>(); if (this is Just <A> && functionMonad != null) { foreach (var function in functionMonad) { if (function != null) { result = new Just <B>(functionMonad.Return()(aValue)); } } if (result == null) { result = new Nothing <B>(); } } return(result); }
public static void MaybePlayaround() { Console.Out.WriteLine("\n-------------------------------------------------------------"); Console.Out.WriteLine("------------------------Maybe playground-----------------------"); Console.Out.WriteLine("-------------------------------------------------------------\n"); // Just 5, use implicit operator for *Maybe* to make a Just directly. Maybe <int> justInt = 5; Console.WriteLine("A new Just<double>: " + justInt.ToString()); Maybe <int> nothingInt = 0; // same as nothingInt = new Nothing<int>(); Console.WriteLine("A new Nothing<double>: " + nothingInt.ToString()); // justInt = 0; or justInt = new Nothing<int>() would make a Nothing out of the justInt Console.WriteLine("A new ListMonad<char>: "); var listMonadChar = new ListMonad <char>() { 'a', 'b', 'c', 'd', 'e', 'f', 'g' } .Visit((x) => { Console.Out.Write(x + ", "); }); Console.WriteLine("\n___________________________________________________________"); Console.WriteLine("A new ListMonad<int>: "); var listMonadInt = new ListMonad <int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } .Visit((x) => { Console.Out.Write(x + ", "); }); Console.WriteLine("\n___________________________________________________________"); Console.WriteLine("A new ListMonad<double>: "); var listMonadDouble = new ListMonad <double>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } .Visit((x) => { Console.Out.Write(x + ", "); }); Console.WriteLine("\n___________________________________________________________"); var intToDoubleFunction = new Func <int, double>(x => { return(x * 0.5); }); Console.WriteLine("A new Just with a function inside: f(x) = x * 0.5 "); var justFunction = new Just <Func <int, double> >(intToDoubleFunction); Console.WriteLine(justFunction.ToString()); Console.WriteLine("___________________________________________________________"); Console.ReadLine(); Console.WriteLine("Visits each combination of the Just 5 and the ListMonad<char>" + "using a lambda and Console.Write inside: "); justInt.Visit((i, c) => { Console.Out.Write(i + "" + c + ", "); }, listMonadChar); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); // Outputs: 1a, 1b, 1c, 1d, 1e, Console.WriteLine("Same with Nothing<int> will output nothing: "); nothingInt.Visit((i, c) => { Console.Out.Write(i + "" + c + ", "); }, listMonadChar); Console.WriteLine("___________________________________________________________"); Console.ReadLine(); Console.WriteLine("Visits each combination of the Just 5 and the ListMonad<int> \n" + "using a lambda and Console.Write inside. Add both values in print out: "); justInt.Visit((x, y) => { Console.Out.Write(x + y + ", "); }, listMonadInt); Console.WriteLine("\nSame with Nothing<int>:"); nothingInt = (Maybe <int>)nothingInt .Visit((x, y) => { Console.Out.Write(x + y + ", "); }, listMonadInt); Console.WriteLine(nothingInt.ToString()); Console.WriteLine("___________________________________________________________"); Console.ReadLine(); Console.Write("Fmap f(x) = x * 0.5 over the Just<int>(5): "); var justDouble = justInt.Fmap(intToDoubleFunction).Visit((x) => { Console.Out.Write(x + "\n"); }); Console.WriteLine("___________________________________________________________"); Console.ReadLine(); Console.Write("App Just<Func>(f(x) = x * 0.5) over the Just<int>(5): "); justDouble = justInt.App(justFunction).Visit((x) => { Console.Out.Write(x + "\n"); }); Console.WriteLine("___________________________________________________________"); Console.ReadLine(); Console.Write("App Just<Func> over the Just<int>(5), \n where the functions returns a new " + "ListMonad<int>() \n with two times the value inside the Just 5. Output: "); var function = new Just <Func <int, Monad <int> > >((x) => { return(new ListMonad <int>() { x, x }); }); var intListMonad = justInt.App(function).Visit((x) => { Console.Out.Write(x + ", "); }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); // The result is a ListMonad<int> // Output: 5, 5, Console.WriteLine("Create a new ListMonad with Func<int, int, double> (x*y, x/y, x%y) inside."); Console.WriteLine("Combinate Just 5 and that functions. Result is Just<int>."); Console.WriteLine("Only last value is returned because this Com function cannot break out of the Just."); Console.WriteLine(); var functionListMonad = new ListMonad <Func <int, int, double> >(); functionListMonad.Append((x, y) => { return(x * y); }); functionListMonad.Append((x, y) => { return(x / (y == 0 ? 1 : y)); }); functionListMonad.Append((x, y) => { return(x % (y == 0 ? 1 : y)); }); functionListMonad.Visit((x) => { Console.Out.WriteLine("Func: " + x); }); var result = justInt.Com(functionListMonad, listMonadInt).Visit((x) => { Console.Out.Write(x + ", "); }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); // Output: 5 Console.WriteLine("Create a new ListMonad with \n" + "Func<int, int, IMonad<double>> (x+y, x-y, x*y, x/y, x%y) inside.\n" + "Where every function packs the result in a new ListMonad<double>.\n" + "Combine the Just 5 and the ListMonad<double> with all the functions.\n" + "The result ListMonad´s are flattned out, and only one result ListMonad<double> \n" + " with all result values is returned: "); Console.WriteLine(); var functionListMonadTwo = new ListMonad <Func <int, double, Monad <double> > >(); functionListMonadTwo.Append((x, y) => { return(new ListMonad <double>() { x + y }); }); functionListMonadTwo.Append((x, y) => { return(new ListMonad <double>() { x - y }); }); functionListMonadTwo.Append((x, y) => { return(new ListMonad <double>() { x *y }); }); functionListMonadTwo.Append((x, y) => { return(new ListMonad <double>() { x / (y == 0 ? 1 : y) }); }); functionListMonadTwo.Append((x, y) => { return(new ListMonad <double>() { x % (y == 0 ? 1 : y) }); }); functionListMonadTwo.Append((x, y) => { return(new Nothing <double>()); }); int counter = 0; var resultTwo = justInt.Com(functionListMonadTwo, listMonadDouble) .Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 10 == 0) { Console.WriteLine(""); } }); // Output: 5*0, 5*1, 5*2,... 5*1, 5/1, 5/2, 5/3, ... 5%1, 5%1, 5%2, 5%3,.... Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); Console.WriteLine("Do the same with the Nothing<int>: "); resultTwo = nothingInt.Com(functionListMonadTwo, listMonadDouble) .Visit((x) => { Console.Out.Write(x + ", "); }); // Output: 5*0, 5*1, 5*2,... 5*1, 5/1, 5/2, 5/3, ... 5%1, 5%1, 5%2, 5%3,.... Console.WriteLine("___________________________________________________________"); Console.ReadLine(); Console.WriteLine("Combinate Just 5 and the ListMonad<int> with only one function ( f(x,y) = x+y ): "); var resultThree = justInt.Com((x, y) => { return(x + y); }, intListMonad) .Visit((x) => { Console.Out.WriteLine(x); }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); Console.WriteLine("Maping a f(x, y) = x*y over the Just 5 and a new Just<int>(10) using LINQ: "); var query = from f in new Just <Func <int, int, int> >((x, y) => { return(x * y); }) from x in justInt from y in new Just <int>(10) select f(x, y); query.Visit((x) => { Console.Out.WriteLine(x + ", "); }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); }