コード例 #1
0
        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(),
            }
                                                             )));
        }
コード例 #2
0
        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);
            }
        }