Take out C # functional programming --3

Foreword

Someone today and chatted to the C # LINQ, find LINQ LINQ I know it seems like most people know not the same, how a different law? In fact, LINQ can also be used to engage in functional programming.

Of course, not to say a few writing lambdaand the like with the use of Java as streamsuch even if the named LINQ, LINQ is actually a another something.

LINQ

In C #, LINQ I believe we have seen the following wording:

IEnumerable<int> EvenNumberFilter(IEnumerable<int> list)
{
    return from c in list where c & 1 == 0 select c;
}

With LINQ syntax above code implements a screening list even.

LINQ is just a set of tools used to facilitate the operation of it, if we want our own if the type of support LINQ syntax, then we need to achieve our type IEnumerable<T>, then you can be so used. . .

Oh, is that right? I understand all that. . . . . .

? ? ? Oh, my God, of course not!

In fact, LINQ and IEnumerable<T>has nothing to do! LINQ is just a set of extensions only method, which is mainly composed of the following methods:

Method name Method Description
Where Data filtering
Select/SelectMany Data Projector
Join/GroupJoin Data connection
OrderBy/ThenBy/OrderByDescending/ThenByDescending Sorting data
GroupBy Data packets
......

The above method corresponds LINQ Keywords: where, select, join, orderby, group...

When the compiler compiles C # code that will convert LINQ syntax syntax extension method calls, for example:

from c in list where c > 5 select c;

It will be compiled into:

list.Where(c => c > 5).Select(c => c);

For another example:

from x1 in list1 join x2 in list2 on x1.k equals x2.k into g select g.u;

It will be compiled into:

list1.GroupJoin(list2, x1 => x1.k, x2 => x2.k, (x1, g) => g.u);

For another example:

from x in list orderby x.k1, x.k2, x.k3;

It will be compiled into:

list.OrderBy(x => x.k1).ThenBy(x => x.k2).ThenBy(x => x.k3);

also:

from c in list1
from d in list2
select c + d;

It will be compiled into:

list1.SelectMany(c => list2, (c, d) => c + d);

Stop, stop!

In addition, the compiler at compile time will always be first and then call the LINQ syntax translation compiled as a method, then, as long as the name of the corresponding method, does not mean you can use the LINQ syntax (escape

So you see this SelectManyis not it. . .

jpg

SelectMany is Monad

Oh my God, you look at this poor SelectMany, this not Monadrequired bindfunction?

Gradually things get interesting again.

We have inherited the spirit of the one, write again Maybe<T>.

Maybe<T>

First, we write an abstract class Maybe<T>.

First, we add it to a Selectmethod for selecting the Maybe<T>data, if it is T, then a return Just<T>, if it is Nothing<T>, then a return Nothing<T>. The equivalent of our returnsfunction:

public abstract class Maybe<T>
{
    public abstract Maybe<U> Select<U>(Func<T, Maybe<U>> f);
}

Then we realize our Justand Nothing:

public class Just<T> : Maybe<T>
{
    private readonly T value;
    public Just(T value) { this.value = value; }

    public override Maybe<U> Select<U>(Func<T, Maybe<U>> f) => f(value);
    public override string ToString() => $"Just {value}";
}

public class Nothing<T> : Maybe<T>
{
    public override Maybe<U> Select<U>(Func<T, Maybe<U>> _) => new Nothing<U>();
    public override string ToString() => "Nothing";
}

Then, we have to Mayberealize bind- that is, to Maybeadd a known SelectManymethod.

public abstract class Maybe<T>
{
    public abstract Maybe<U> Select<U>(Func<T, Maybe<U>> f);

    public Maybe<V> SelectMany<U, V>(Func<T, Maybe<U>> k, Func<T, U, V> s)
        => Select(x => k(x).Select(y => new Just<V>(s(x, y))));
}

So far, Maybe<T>achieved over! What, on this? ? So how to use it? Exciting time coming!

First, we create a few Maybe<int>:

var x = new Just<int>(3);
var y = new Just<int>(7);
var z = new Nothing<int>();

We were then calculated using the LINQ x + y, x + z:

var u = from x0 in x from y0 in y select x0 + y0;
var v = from x0 in x from z0 in z select x0 + z0;

Console.WriteLine(u);
Console.WriteLine(v);

Output:

Just 10
Nothing

perfect! The above LINQ compiled as:

var u = x.SelectMany(_ => y, (x0, y0) => x0 + y0);
var v = x.SelectMany(_ => z, (x0, z0) => x0 + z0);

At this time, functions kas int -> Maybe<int>, and function sas (int, int) -> int, an addition function.

Function kparameters we do not care, it is used as a selector, we only need to generate a make Maybe<int>, and then using the function sof the two intvalues do adder, and the results into a packed Just<int>inside the can.

This process, if there are either produced Nothing, the result is always the follow-up operation Nothing, because Nothing.Select(...)still Nothing.

A little extension

We give this Maybe<T>plus a Where:

public abstract class Maybe<T>
{
    public abstract Maybe<U> Select<U>(Func<T, Maybe<U>> f);

    public Maybe<V> SelectMany<U, V>(Func<T, Maybe<U>> k, Func<T, U, V> s)
        => Select(x => k(x).Select(y => new Just<V>(s(x, y))));

    public Maybe<U> Where(Func<Maybe<T>, bool> f) => f(this) ? this : new Nothing<T>();
}

Then we can play:

var just = from c in x where true select c;
var nothing = from c in x where false select c;

Console.WriteLine(just);
Console.WriteLine(nothing);

When the condition returns Just, otherwise it returns Nothing. Above will output:

Just 3
Nothing

There is a smell inside (escape

postscript

Subsequent articles in this series will be written in the mortgage, if C # a little disappointing, the Discriminated Unions, Higher Kinded Generics and Type Classes characteristics plus, and we continue.

Guess you like

Origin www.cnblogs.com/hez2010/p/12590389.html
Recommended