2013-10-31 37 views
2

幾天前我一直在#haskell IRC房間裏閒逛,有人提到C#有語法來做monadic理解這是什麼意思?C#中的Monadic理解語法

如果我理解正確,monadic理解只是一種排序bind操作的方式,哪種類型的聲音就像是do表示法?那是對的嗎?

問題是,我沒有看到這在C#中。據我所知IEnumerable<T>是一個monad,其中SelectMany是它的bind函數,因爲它的簽名是A -> IEnumerable<B>。隨着富有想象力的舒展,我們可以做

from x in xs 
from y in ys 

換算成(我不是100%肯定這裏

xs.SelectMany(x => ys.Select(y => y), (x, y) => ...) 

但即使這是真的,我們想到的作爲monad理解語法的LINQ,它仍然只適用於IEnumerable<T>。我們確實在C#中有其他單子,如Task<T>,但我們如何在這些上使用LINQ?

這個問題中的許多假設都可能是完全錯誤的,因爲我仍然試圖掌握一些monad魔法的東西。請糾正我,如果我錯了:)

回答

6

LINQ查詢語法僅僅是語法糖,並不知道任何關於IEnumerable<>,這就是爲什麼你可以用它來做其他事情。

如果檢查C# language specification,它描述瞭如何LINQ的查詢表達式應該在第7.16.2

C#語言沒有指定查詢表達式的執行語義轉化。相反,查詢表達式被轉換成了符合查詢表達式模式的方法的調用(§7.16.3)。具體而言,查詢表達式被轉換爲名爲Where,Select,SelectMany,Join,GroupJoin,OrderBy,OrderByDescending,ThenBy,ThenByDescending,GroupBy和Cast的方法的調用。這些方法預期具有特定的簽名和結果類型,如§ 7.16.3。這些方法可以是查詢對象的實例方法,也可以是對象外部的擴展方法,它們實現查詢的實際執行。

你的具體例子被描述爲

從子句的第二後跟一個選擇子句

from x1 in e1 
from x2 in e2 
select v 

被翻譯成

的查詢表達式
(e1) . SelectMany(x1 => e2 , (x1 , x2) => v) 

因此,使用從您的示例中的變量名,即有一個方法Treturned SelectMany(Func<Tx,Tys>, Func<Tx,Ty,Treturned>)任何xs可以在語句中使用類似

Treturned returned = 
    from x in xs 
    from y in ys 
    select r; 

這將編譯什麼時候

Treturned returned = xs.SelectMany(x => ys, (x, y) => r); 

呢,這任何時候這種方法都存在於xs上。 SelectMany存在IEnumerable<>這一事實並不妨礙我們將其他類型與方法或擴展方法同名。

C#可以從它知道xs是什麼的事實推斷出lambda表達式的類型,並從中可以查找xsSelectMany參數的類型。