小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

拿 C# 搞函數(shù)式編程 - 3

 行者花雕 2021-04-09

前言

今天和某個人聊天聊到了 C# 的 LINQ,發(fā)現(xiàn)我認識的 LINQ 似乎和大多數(shù)人認識的 LINQ 不太一樣,怎么個不一樣法呢?其實 LINQ 也可以用來搞函數(shù)式編程。

當然,并不是說寫幾個 lambda 和用用像 Java 那樣的 stream 之類的就算叫做 LINQ 了,LINQ 其實是一個另外的一些東西。

LINQ

在 C# 中,相信大家都見過如下的 LINQ 寫法:

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

以上代碼借助 LINQ 的語法實現(xiàn)了對一個列表中的偶數(shù)的篩選。

LINQ 只是一個用于方便對集合進行操作的工具而已,如果我們?nèi)绻胱屛覀冏约旱念愋椭С?LINQ 語法,那么我們需要讓我們的類型實現(xiàn) IEnumerable<T>,然后就可以這么用了。。。

哦,原來是這樣的嗎?那我全都懂了。。。。。。

???哦,我的老天,當然不是!

其實 LINQ 和 IEnumerable<T> 完全沒有關系!LINQ 只是一組擴展方法而已,它主要由以下方法組成:

方法名稱 方法說明
Where 數(shù)據(jù)篩選
Select/SelectMany 數(shù)據(jù)投影
Join/GroupJoin 數(shù)據(jù)聯(lián)接
OrderBy/ThenBy/OrderByDescending/ThenByDescending 數(shù)據(jù)排序
GroupBy 數(shù)據(jù)分組
......

以上方法對應 LINQ 關鍵字:where, select, join, orderby, group...

在編譯器編譯 C# 代碼時,會將 LINQ 語法轉(zhuǎn)換為擴展方法調(diào)用的語法,例如:

from c in list where c > 5 select c;

會被編譯成:

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

再例如:

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

會被編譯成:

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

再例如:

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

會被編譯成:

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

再有:

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

會被編譯成:

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

停停停!

此外,編譯器在編譯的時候總是會先將 LINQ 語法翻譯為方法調(diào)用后再編譯,那么,只要有對應名字的方法,不就意味著可以用 LINQ 語法了(逃

那么你看這個 SelectMany 是不是。。。

jpg

SelectMany is Monad

哦我的上帝,你瞧瞧這個可憐的 SelectMany,這難道不是 Monad 需要的 bind 函數(shù)?

事情逐漸變得有趣了起來。

我們繼承上一篇的精神,再寫一次 Maybe<T>。

Maybe<T>

首先,我們寫一個抽象類 Maybe<T>。

首先我們給它加一個 Select 方法用于選擇 Maybe<T> 中的數(shù)據(jù),如果是 T,那么返回一個 Just<T>,如果是 Nothing<T>,那么返回一個 Nothing<T>。相當于我們的 returns 函數(shù):

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

然后我們實現(xiàn)我們的 JustNothing

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";
}

然后,我們給 Maybe 實現(xiàn) bind —— 即給 Maybe 加上一個叫做 SelectMany 的方法。

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))));
}

至此,Maybe<T> 實現(xiàn)完了!什么,就這??那么怎么用呢?激動人心的時刻來了!

首先,我們創(chuàng)建幾個 Maybe<int>

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

然后我們分別利用 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);

輸出結(jié)果:

Just 10
Nothing

完美!上面的 LINQ 被編譯成了:

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

此時,函數(shù) kint -> Maybe<int>,而函數(shù) s(int, int) -> int,是一個加法函數(shù)。

函數(shù) k 的參數(shù)我們并不關心,它用作一個 selector,我們只需要讓它產(chǎn)生一個 Maybe<int>,然后利用函數(shù) s 將兩個 int 的值做加法運算,并把結(jié)果包裝到一個 Just<int> 里面即可。

這個過程中,如果有任何一方產(chǎn)生了 Nothing,則后續(xù)運算結(jié)果永遠都是 Nothing,因為 Nothing.Select(...) 還是 Nothing。

一點擴展

我們再給這個 Maybe<T> 加一個 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>();
}

然后我們就可以玩:

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);

當滿足條件的時候返回 Just,否則返回 Nothing。上述代碼將輸出:

Just 3
Nothing

有內(nèi)味了(逃

后記

該系列的后續(xù)文章將按揭編寫,如果 C# 爭氣一點,把 Discriminated Unions、Higher Kinded Generics 和 Type Classes 特性加上了,我們再繼續(xù)。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多