public static ListMonad <T> ToListMonad <T>(this Monad <T> value) { ListMonad <T> result = new ListMonad <T>(); foreach (T element in value) { result.Add(element); } return(result); }
public static ListMonad <A> ToListMonad <A>(this IList <A> value) { ListMonad <A> result = new ListMonad <A>(); foreach (A element in value) { result.Append(element); } return(result); }
/// <summary> /// Map the given function to each element in this ListMonad, /// and put the result in a new ListMonad of the result type. /// </summary> /// <typeparam name="B">Type of the value inside the result ListMonad.</typeparam> /// <param name="function">The function to map over the values.</param> /// <returns>The result ListMonad<B></returns> public override Monad <B> Fmap <B>(Func <A, B> function) { ListMonad <B> resultEnumerable = new ListMonad <B>(); foreach (A element in list) { resultEnumerable.Append(function(element)); } return(resultEnumerable); }
public override Monad <B> Fmap <B>(Func <A, int, B> function) { ListMonad <B> resultListMonad = new ListMonad <B>(); int index = 0; foreach (A element in list) { resultListMonad.Append(function(element, index)); // Get the value of type B out of the result IMonad<B>, no matter what monad the result is. index++; } return(resultListMonad); }
public override Monad <C> Com <B, C>(Func <A, B, Monad <C> > function, Monad <B> mOther) { ListMonad <C> result = new ListMonad <C>(); foreach (A a in list) { foreach (B b in mOther) { result.Concatenate(function(a, b)); } } return(result); }
public override Monad <C> Com <B, C>(Func <A, B, C> function, Monad <B> mOther) { ListMonad <C> resultListMonad = new ListMonad <C>(); foreach (A elementThis in list) { foreach (B elementOther in mOther) { resultListMonad.Append(function(elementThis, elementOther)); } } return(resultListMonad); }
public override Monad <C> Com <B, C>(Monad <Func <A, B, C> > functionMonad, Monad <B> mOther) { ListMonad <C> resultListMonad = new ListMonad <C>(); foreach (Func <A, B, C> f in functionMonad) { foreach (A a in list) { foreach (B b in mOther) { resultListMonad.Append(f(a, b)); } } } return(resultListMonad); }
/// <summary> /// Map each function inside the given Monad over each element in this ListMonad, /// and put all the values inside the result monads into a new ListMonad of the type B. /// </summary> /// <typeparam name="B">The type inside the result ListMonad.</typeparam> /// <param name="functionMonad">The monad that has functions inside.</param> /// <returns>The new ListMonad of type B.</returns> public override Monad <B> App <B>(Monad <Func <A, Monad <B> > > functionMonad) { ListMonad <B> result = new ListMonad <B>(); foreach (Func <A, Monad <B> > function in functionMonad) { // function can be null, for example when the functionMonad is a Maybe with Nothing<Func<A, IMonad<B>> then default(Func<A, IMonad<B>>) returns null // we could check for IMonad as Maybe and then check for isNothing, but then ListMonad have to "know" Maybe, i dont like that. if (function != null) { foreach (A element in list) // calculate function result for each element in this ListFunctor<T> { result.Concatenate(function(element)); } } } return(result); }
public override Monad <B> Fmap <B>(Func <CacheEntry <K, V>, B> function) { ListMonad <B> result = new ListMonad <B>(); Lock.EnterWriteLock(); try { foreach (var element in cacheDict) { result.Add(function(element.Value)); } } finally { Lock.ExitWriteLock(); } return(result); }
public override Monad <C> Com <B, C>(Func <CacheEntry <K, V>, B, C> function, Monad <B> mOther) { ListMonad <C> result = new ListMonad <C>(); Lock.EnterWriteLock(); try { foreach (var element in cacheDict.Values) { foreach (var elementB in mOther) { result.Add(function(element, elementB)); } } } finally { Lock.ExitWriteLock(); } return(result); }
public override Monad <B> App <B>(Monad <Func <CacheEntry <K, V>, B> > functionMonad) { ListMonad <B> result = new ListMonad <B>(); Lock.EnterWriteLock(); try { foreach (var element in cacheDict.Values) { foreach (var func in functionMonad) { result.Add(func(element)); } } } finally { Lock.ExitWriteLock(); } return(result); }
public override Monad <B> Bind <B>(Func <CacheEntry <K, V>, Monad <B> > func) { ListMonad <B> result = new ListMonad <B>(); Lock.EnterWriteLock(); try { foreach (var element in cacheDict.Values) { foreach (var fRes in func(element)) { result.Add(fRes); } } } finally { Lock.ExitWriteLock(); } return(result); }
public static void ListMonadLinqAndBindPlayground() { var bindResult1 = new ListMonad <string>() { "1. ", "2. " }.Fmap(a => "Hello World!".ToIdentity().Fmap(b => (new DateTime(2010, 1, 11)).ToMaybe().Fmap(c => a + ", " + b.ToString() + ", " + c.ToShortDateString()).Return()).Return()); Console.WriteLine(bindResult1); Console.ReadLine(); var bindResult2 = from str in new ListMonad <string>() { "1. ", "2. " } from h in "Hello World!".ToIdentity() from b in 7.ToIdentity() from dt in (new DateTime(2010, 1, 11)).ToMaybe() select str + h + " " + b.ToString() + " " + dt.ToShortDateString(); Console.WriteLine(bindResult2); Console.ReadLine(); var bindResult3 = " This is a bind test".ToIdentity().Bind(a => "Hello World!".ToIdentity().Bind(b => (new DateTime(2010, 1, 11)).ToMaybe().Bind(c => (a + ", " + b.ToString() + ", " + c.ToShortDateString()).ToIdentity()))); Console.WriteLine(bindResult3); Console.ReadLine(); Monad <string> idString = from a in "Hello World!".ToIdentity() from b in 7.ToIdentity() from c in (new DateTime(2010, 1, 11)).ToIdentity() select a + ", " + b.ToString() + ", " + c.ToShortDateString(); Console.WriteLine(idString); Console.ReadLine(); var listMInt = new ListMonad <int>() { 1, 2, 3, 4, 5 }; var listMDbl = new ListMonad <double> { 1.5, 2.5, 3.5, 4.5, 5.5 }; var listMChar = new ListMonad <Char>() { 'a', 'b', 'c', 'd', 'e' }; // The query is a ListMonad<String> because the monad that calles select, // is a ListMonad (listMInt). var listMString = from i in listMInt from c in listMChar select i + ":" + c; Console.WriteLine(listMString); Console.ReadLine(); var result3 = from i in listMInt from d in listMDbl from c in listMChar select c + ") " + Math.Pow(i, d) + ", "; Console.WriteLine(result3); Console.ReadLine(); var result4 = from i in listMInt from d in listMDbl from c in listMChar select(c + ") " + Math.Pow(i, d) + ", ").ToIdentity(); Console.WriteLine(result4); Console.ReadLine(); var result5 = from i in listMInt from d in listMDbl select i + ") " + Math.Pow(i, d) + ", "; Console.WriteLine(result5); Console.ReadLine(); var result6 = listMInt.Com((i, d) => (i + ") " + Math.Pow(i, d) + ", ").ToIdentity(), listMDbl); Console.WriteLine(result6); Console.ReadLine(); var result7 = from i in listMInt where i % 2 == 0 from d in new ListMonad <double>() { 1.0, 2.0, 3.0, 4.0, 5.0 } where d % 2 == 0 select i + "^" + d + " = " + Math.Pow(i, d) + ", "; Console.WriteLine(result7); Console.ReadLine(); }
public static void ListMonadOperatorPlayground() { Console.Out.WriteLine("\n-------------------------------------------------------------"); Console.Out.WriteLine("------------------------Operator playground-------------------"); Console.Out.WriteLine("-------------------------------------------------------------\n"); int counter = 0; Console.Out.WriteLine("Create two lists [0..9]: "); ListMonad <double> listMonadDouble = new ListMonad <double>() { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 }; ListMonad <double> listMonadDoubleTwo = new ListMonad <double>() { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 }; // Functions for second App function. Func <double, Monad <double> > doubleIMonadDoubleFun1 = (x) => { return(new Just <double>(x * x)); }; Func <double, Monad <double> > doubleIMonadDoubleFun2 = (x) => { return(new Just <double>(x * x * x)); }; Func <double, Monad <double> > doubleIMonadDoubleFun3 = (x) => { return(new Just <double>(x * x * x * x)); }; Func <double, Monad <double> > doubleIMonadDoubleFun4 = (x) => { return(new Just <double>(x * x * x * x * x)); }; Func <double, Monad <double> > doubleIMonadDoubleFun5 = (x) => { return(new ListMonad <double>() { x + 1, x - 1 }); }; var listMonadFunc1 = new ListMonad <Func <double, Monad <double> > >(); listMonadFunc1.Append(doubleIMonadDoubleFun1); listMonadFunc1.Append(doubleIMonadDoubleFun2); listMonadFunc1.Append(doubleIMonadDoubleFun3); listMonadFunc1.Append(doubleIMonadDoubleFun4); listMonadFunc1.Append(doubleIMonadDoubleFun5); // Functions for combination Func <double, double, double> doubleDoubleDoubleFunc1 = (x, y) => { return(x + y); }; Func <double, double, double> doubleDoubleDoubleFunc2 = (x, y) => { return(x - y); }; Func <double, double, double> doubleDoubleDoubleFunc3 = (x, y) => { return(x * y); }; Func <double, double, double> doubleDoubleDoubleFunc14 = (x, y) => { return(x / y); }; Func <double, double, double> doubleDoubleDoubleFunc5 = (x, y) => { return(x % y); }; var listMonadFunc2 = new ListMonad <Func <double, double, double> >() { doubleDoubleDoubleFunc1, doubleDoubleDoubleFunc2, doubleDoubleDoubleFunc3, doubleDoubleDoubleFunc14, doubleDoubleDoubleFunc5 }; // Functions for combination with IMonad as result. Func <double, double, Monad <double> > intDoubleIMonadDoubleFunc1 = (x, y) => { return(new Just <double>(x + y)); }; Func <double, double, Monad <double> > intDoubleIMonadDoubleFunc2 = (x, y) => { return(new Just <double>(x - y)); }; Func <double, double, Monad <double> > intDoubleIMonadDoubleFunc3 = (x, y) => { return(new Just <double>(x * y)); }; Func <double, double, Monad <double> > intDoubleIMonadDoubleFunc4 = (x, y) => { return(new Just <double>(x / y)); }; Func <double, double, Monad <double> > intDoubleIMonadDoubleFunc5 = (x, y) => { return(new ListMonad <double>() { x % y }); }; Func <double, double, Monad <double> > intDoubleIMonadDoubleFunc6 = (x, y) => { return(new ListMonad <double>() { x *y *y, x *y *y *y }); }; Func <double, double, Monad <double> > intDoubleIMonadDoubleFunc7 = (x, y) => { return(new Nothing <double>()); }; var listMonadFunc3 = new ListMonad <Func <double, double, Monad <double> > >() { intDoubleIMonadDoubleFunc1, intDoubleIMonadDoubleFunc2, intDoubleIMonadDoubleFunc3, intDoubleIMonadDoubleFunc4, intDoubleIMonadDoubleFunc5, intDoubleIMonadDoubleFunc6, intDoubleIMonadDoubleFunc7 }; Console.WriteLine("fmap f(x) = x * 0.5 over [1,0..9.0] with \" / \" operator"); var result = (listMonadDouble / ((x) => { return(x * 0.5); })).Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); Console.WriteLine("App functions [x^2, x^3, x^4, x^5, [x+1, x-1]] \n" + " over [1,0..9.0] with \" * \" operator"); var resultTwo = (listMonadDouble * listMonadFunc1).Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); // Create a tupel with the ListMonad with functions inside // and with the other ListMonad with double values inside // because the \"*\" operator can have only one other argument. // it sad there are no way for custom operators in C# // and there are no operator that take tree arguments and can be overloaded. var funcMonadTupel = new Tuple <Monad <Func <double, double, double> >, Monad <double> >(listMonadFunc2, listMonadDoubleTwo); counter = 0; Console.WriteLine("Combinate [1.0,..,9.0] with [1.0,..,9.0] and functions \n" + " [x+y, x-y, x*y, x/y, x%y]"); var resultThree = (listMonadDouble * funcMonadTupel) .Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } if (counter % (9 * 9) == 0) { Console.WriteLine("-------------------------------------------"); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); var funcMonadTupelTwo = new Tuple <Monad <Func <double, double, Monad <double> > >, Monad <double> > (listMonadFunc3, listMonadDoubleTwo); Console.WriteLine("Combinate [1.0,..,9.0] with [1.0,..,9.0] and functions \n" + " [x+y, x-y, x*y, x/y, x%y, [x*y^2, x*y^3]]:"); var resultFour = (listMonadDouble * funcMonadTupelTwo) .Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } if (counter % (9 * 9) == 0) { Console.WriteLine("-------------------------------------------"); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); Console.WriteLine("[1.0,..,9.0] + [1.0,..,9.0] + Just(1000.0) + Nothing \n" + " Fmap -> App -> Com -> Com2nd -> Visit \n" + " This will take a while!! Are you ready, then press enter :-D :"); Console.ReadLine(); // Concat both double ListMonad´s to get a bigger list // and only to show that its possible // concat a Just(1000.0) and a Nothing<double> to the result list too. var resultFive = (listMonadDouble + listMonadDoubleTwo) .Append(new Just <double>(1000.0)) .Append(new Nothing <double>()); var resultSix = (ListMonad <double>)resultFive; // This line is done the whole operatione! // Without one loop. resultSix = resultSix / ((x) => { return(x * 100.0); }) * funcMonadTupel * funcMonadTupelTwo; resultSix.Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } if (counter % (9 * 9) == 0) { Console.WriteLine("-------------------------------------------"); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); }
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(); }
public static void ListMonadPlayground() { Console.Out.WriteLine("\n-------------------------------------------------------------"); Console.Out.WriteLine("------------------------ListMonad playground-------------------"); Console.Out.WriteLine("-------------------------------------------------------------\n"); Console.Out.WriteLine("Create two lists [1..5] and [J(1)..(J5)]: "); ListMonad <int> listMonadInt = new ListMonad <int>() { 1, 2, 3, 4, 5 }; ListMonad <double> listMonadDouble = new ListMonad <double>() { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 }; // Because Maybe class has an implicit operator it can be written very cool and easy like a normal list. ListMonad <Maybe <int> > listMonadMaybeInt = new ListMonad <Maybe <int> >() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // Functions for Fmap and first App function. Func <int, double> intDoubleFunc1 = (x) => { return(0.5 * x); }; Func <int, double> intDoubleFunc2 = (x) => { return(0.7 * x); }; Console.WriteLine("Fmap f(x) = 0.5 * x over [1,..5,]"); int counter = 0; listMonadInt.Fmap(intDoubleFunc1).Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 5 == 0) { Console.WriteLine(""); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); Console.WriteLine("App [f(x)=0.5*x, f(x)=0.7*x] over [1,..,5]"); var listMonadintDoubleFunc = new ListMonad <Func <int, double> >() { intDoubleFunc1, intDoubleFunc2 }; counter = 0; listMonadInt.App(listMonadintDoubleFunc).Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 5 == 0) { Console.WriteLine(""); } if (counter % (5 * 5) == 0) { Console.WriteLine("-----------------------------------------"); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); // Functions for second App function. Func <int, Monad <double> > intIMonadIntDoubleFunc1 = (x) => { return(new Just <double>(x * x)); }; Func <int, Monad <double> > intIMonadIntDoubleFunc2 = (x) => { return(new Just <double>(x * x * x)); }; Func <int, Monad <double> > intIMonadIntDoubleFunc3 = (x) => { return(new Just <double>(x * x * x * x)); }; Func <int, Monad <double> > intIMonadIntDoubleFunc4 = (x) => { return(new Just <double>(x * x * x * x * x)); }; Func <int, Monad <double> > intIMonadIntDoubleFunc5 = (x) => { return(new ListMonad <double>() { x + 1, x - 1 }); }; var listMonadIMonadIntDoubleFunc = new ListMonad <Func <int, Monad <double> > >(); listMonadIMonadIntDoubleFunc.Append(intIMonadIntDoubleFunc1); listMonadIMonadIntDoubleFunc.Append(intIMonadIntDoubleFunc2); listMonadIMonadIntDoubleFunc.Append(intIMonadIntDoubleFunc3); listMonadIMonadIntDoubleFunc.Append(intIMonadIntDoubleFunc4); listMonadIMonadIntDoubleFunc.Append(intIMonadIntDoubleFunc5); Console.WriteLine("App [Just(x^2), Just(x^3), Just(x^4), Just(x^5) ListMonad{x+1, x-1} over [1,..,5]"); listMonadInt.App(listMonadIMonadIntDoubleFunc).Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 5 == 0) { Console.WriteLine(""); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); // Functions for combination Func <int, double, double> intDoubleDoubleFunc1 = (x, y) => { return((double)x + y); }; Func <int, double, double> intDoubleDoubleFunc2 = (x, y) => { return((double)x - y); }; Func <int, double, double> intDoubleDoubleFunc3 = (x, y) => { return((double)x * y); }; Func <int, double, double> intDoubleDoubleFunc4 = (x, y) => { return((double)x / y); }; Func <int, double, double> intDoubleDoubleFunc5 = (x, y) => { return((double)x % y); }; var listMonadIntDoubleDoubleFunc = new ListMonad <Func <int, double, double> >() { intDoubleDoubleFunc1, intDoubleDoubleFunc2, intDoubleDoubleFunc3, intDoubleDoubleFunc4, intDoubleDoubleFunc5 }; Console.WriteLine("Combinate [1..5] and [1.0,..,9.0] with 'normal' result value and function +:"); counter = 0; listMonadInt.Com(intDoubleDoubleFunc1, listMonadDouble) .Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); Console.WriteLine("Combinate [1..5] and [1.0,..,9.0] 'normal' result value and functions [+, -, *, /, %]: "); counter = 0; listMonadInt.Com(listMonadIntDoubleDoubleFunc, listMonadDouble) .Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } if (counter % (5 * 9) == 0) { Console.WriteLine("------------------------------------------------"); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); // Functions for combination with IMonad as result. Func <int, double, Monad <double> > intDoubleIMonadDoubleFunc1 = (x, y) => { return(new Just <double>((double)x + y)); }; Func <int, double, Monad <double> > intDoubleIMonadDoubleFunc2 = (x, y) => { return(new Just <double>((double)x - y)); }; Func <int, double, Monad <double> > intDoubleIMonadDoubleFunc3 = (x, y) => { return(new Just <double>((double)x * y)); }; Func <int, double, Monad <double> > intDoubleIMonadDoubleFunc4 = (x, y) => { return(new Just <double>((double)x / y)); }; Func <int, double, Monad <double> > intDoubleIMonadDoubleFunc5 = (x, y) => { return(new ListMonad <double>() { (double)x % y }); }; Func <int, double, Monad <double> > intDoubleIMonadDoubleFunc6 = (x, y) => { return(new ListMonad <double>() { (double)x * y * y, (double)x * y * y * y }); }; Func <int, double, Monad <double> > intDoubleIMonadDoubleFunc7 = (x, y) => { return(new Nothing <double>()); }; var listMonadIntDoubleIMonadDoubleFunc = new ListMonad <Func <int, double, Monad <double> > >() { intDoubleIMonadDoubleFunc1, intDoubleIMonadDoubleFunc2, intDoubleIMonadDoubleFunc3, intDoubleIMonadDoubleFunc4, intDoubleIMonadDoubleFunc5, intDoubleIMonadDoubleFunc6, intDoubleIMonadDoubleFunc7 }; Console.WriteLine("Combination with IMonad function results."); Console.WriteLine("List1[1,..,5], List2[1.0,..,9.0] and function +"); counter = 0; listMonadInt.Com(intDoubleIMonadDoubleFunc1, listMonadDouble) .Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } if (counter % (5 * 9) == 0) { Console.WriteLine("------------------------------------------------"); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); Console.WriteLine("Combination with IMonad function results."); Console.WriteLine("List1[1,..,5], List2[1.0,..,9.0] and " + "functions [+, -, *, /, %, [x*y*y, x*y*y*y], Nothing]"); counter = 0; listMonadInt.Com(listMonadIntDoubleIMonadDoubleFunc, listMonadDouble) .Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } if (counter % (5 * 9) == 0) { Console.WriteLine("------------------------------------------------"); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); // Visit with other IMonad Console.WriteLine("Visit with other IMonad and add (+) values in output."); counter = 0; listMonadInt.Visit <double>((x, y) => { Console.Write(x * y + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } }, listMonadDouble); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); Console.WriteLine("Function applying with Linq: \n" + " from f in [+, -, *, %]\n" + " from x in [1,..,5]\n" + " from y in [1.0,..,9.0] \n" + " select f(x,y) \n"); var query = from f in listMonadIntDoubleDoubleFunc from x in listMonadInt from y in listMonadDouble select f(x, y); counter = 0; query.Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } if (counter % (5 * 9) == 0) { Console.WriteLine("------------------------------------------------"); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); Console.WriteLine("Function applying with Linq: "); var query2 = from f in listMonadIntDoubleIMonadDoubleFunc from x in listMonadInt from y in listMonadDouble select f(x, y); counter = 0; query2.Visit((x) => { Console.Out.Write(x + ", "); counter++; if (counter % 9 == 0) { Console.WriteLine(""); } if (counter % (5 * 9) == 0) { Console.WriteLine("------------------------------------------------"); } }); Console.WriteLine("\n___________________________________________________________"); Console.ReadLine(); }