public static async Task Run() { // Add two numbers and make a string var AddStr = FuncA.Create((int x, int y) => (x + y).ToString()); // Two numbers with curry var Add = FuncA.Create((int x, int y) => (x + y)); var Multiply = FuncA.Create((int x, int y) => (x * y)); // String concat var StrCat = FuncA.Create((string x, string y) => $"{x}{y}"); // Create a ListA with some FuncAs in it var add_1_then_2_then_3 = ListA.Create(new[] { AddStr.Invoke(1), AddStr.Invoke(2), AddStr.Invoke(3) }); var a = new ListA <int> { 1, 2, 3 }; var res10_list = ((IApplicative <ListA <int>, ListA <object>, int>)a); // ApplyFrom is using reverse parameter order compared to Haskell's <*> // This is so we can restrict the type on the input parameter to need to be FuncA<> var res10_appliedFrom = res10_list .ApplyFromImpl <ListA <FuncA <int, string> >, FuncA <int, string>, ListA <string>, string>( add_1_then_2_then_3 ); var res10 = res10_appliedFrom as ListA <string>; // <*> ApplyTo as an extension method is equivalent to Haskell <*> var res11 = add_1_then_2_then_3 .AppliedTo <int, string>(a); // AppliedTo with multiple lists and currying functions var b = new ListA <int> { 1, 2 }; var c = new ListA <int> { 3, 4 }; var add_mult = ListA.Create(Add.Invoke(1), Add.Invoke(2), Multiply.Invoke(1), Multiply.Invoke(2)); var res12 = add_mult .AppliedTo <int, int>(c); // We can now do [(+),(*)] <*> [1,2] <*> [3,4] var add_mult_two_lists = ListA.Create(Add, Multiply); var res13 = add_mult_two_lists .AppliedTo <int, FuncA <int, int> >(b).Show(select: x => x.Count()) .AppliedTo <int, int>(c); // // Don't even need the type parameters! // var res14 = add_mult_two_lists // .AppliedTo(a) // .AppliedTo(b); Console.WriteLine(JsonSerializer.PrettyPrint(JsonSerializer.Serialize( new { res10 = await res10.Unbox(), res11 = await res11.Unbox(), res12 = await res12.Unbox(), res13 = await res13.Unbox(), // res14 = await res14.Unbox(), } ))); }
public static async Task Run() { // Create a functor Lazy<int> containing a 5. var a = new LazyF <int>(() => 5); // Example for direct use of IFunctor interface. var res1_functor = ((IFunctor <LazyF <int>, int>)a); var res1_exec = res1_functor.FmapImpl <LazyF <string>, string>( x => (x + 2).ToString()); var res1 = ((LazyF <string>)res1_exec); // Instead of x.Value as above, we can call Unbox on the input to the function. var res2 = a.Fmap <int, string>(x => (x + 3).ToString()); // Type argument are inferred now that we have simplified it var res3 = a.Fmap(x => (x + 4).ToString()); // There is also support for chaining! var res4 = a.Fmap(x => x + 5).Fmap(x => x.ToString()); Console.WriteLine(JsonSerializer.PrettyPrint(JsonSerializer.Serialize( new { res1 = await res1.Unbox(), res2 = await res2.Unbox(), res3 = await res3.Unbox(), res4 = await res4.Unbox() } ))); // // Let's spice it up and use a Task var b = new LazyTaskF <int>(() => Task.FromResult(5)); var res5 = b.Fmap(x => x + 6).Fmap(x => x.ToString()); // Unsurprising, it behaves exactly like Lazy from before.. // // Lets actually do something then. var requestUri = "https://www.dennis-s.dk"; var res6 = LazyTaskF.Create( () => new System.Net.Http.HttpClient().GetStreamAsync(requestUri)) .Fmap(x => WriteToFileAsync("index.html", x)) .Fmap(t => t.ContinueWith(x => x.Result.Close())) .Fmap(t => t.ContinueWith(_ => System.IO.File.ReadAllTextAsync("index.html"))) .Fmap(t => t.ContinueWith(x => x.Result.ToCharArray().Count())); // Not impressive huh.. Looks a lot like we could just use a few "await" instead of all those Fmaps. // Lets try a sequence. var c = new[] { 1, 2, 3 }; var res7 = ListA.Create(c) .Fmap(x => x + 1) .Fmap(x => x.ToString()); // As expected, it looks exactly like Linq. // We can use it to do multiple things, but again, not very interesting var requestUris = new[] { "https://www.dennis-s.dk", "https://www.dennis-s.dk/404" }; var res8 = ListA.Create(requestUris) .Fmap( url => LazyTaskF.Create <System.IO.Stream>( () => new System.Net.Http.HttpClient().GetStreamAsync(url)) .Fmap(x => WriteToFileAsync("index.html", x)) .Fmap(t => t.ContinueWith(x => x.Result.Close())) .Fmap(t => t.ContinueWith(_ => System.IO.File.ReadAllTextAsync("index.html"))) .Fmap(t => t.ContinueWith(x => x.Result.ToCharArray().Count())) ); Console.WriteLine(JsonSerializer.PrettyPrint(JsonSerializer.Serialize( new { res5 = await res5.Unbox(), res6 = await res6.Unbox(), res7 = await res7.Unbox(), res8 = await res8.Unbox() } ))); // Helper method to return a written filestream async Task <System.IO.FileStream> WriteToFileAsync(string filename, System.IO.Stream x) { var file = new System.IO.FileStream(filename, System.IO.FileMode.Create); await x.CopyToAsync(file); return(file); } }