C#中的Monadic理解语法

Jak*_*old 3 c# monads haskell functional-programming

几天前我一直在#haskell IRC房间里闲逛,有人提到C#具有进行monadic理解的语法.这是什么意思?

如果我理解正确,monadic理解只是一种排序bind操作的方式,这听起来像一种do符号?那是对的吗?

问题是我在C#中没有看到这个.据我所知IEnumerable<T>,monad SelectMany是它的bind功能,因为它的标志是A -> IEnumerable<B>.只需一点想象力,我们就可以做到

from x in xs
from y in ys
Run Code Online (Sandbox Code Playgroud)

这转化为(我不是100%肯定在这里)

xs.SelectMany(x => ys.Select(y => y), (x, y) => ...)
Run Code Online (Sandbox Code Playgroud)

但即使这是真的,我们认为LINQ是monad理解语法,它仍然只适用于IEnumerable<T>.我们在C#中有其他monad Task<T>,但是我们怎么能在那些上使用LINQ?

这个问题中的许多假设可能是完全错误的,因为我仍然试图掌握一些monad神奇的东西.如果我错了请纠正我:)

Cir*_*dec 7

LINQ查询语法只是语法糖,并不知道任何事情IEnumerable<>,这就是为什么你可以将它用于其他事情.

如果检查C#语言规范,它将描述如何在7.16.2节中转换LINQ的查询表达式

C#语言未指定查询表达式的执行语义.相反,查询表达式被转换为符合查询表达式模式(第7.16.3节)的方法的调用.具体来说,查询表达式被转换为名为Where,Select,SelectMany,Join,GroupJoin,OrderBy,OrderByDescending,ThenBy,ThenByDescending,GroupBy和Cast的方法的调用.这些方法应具有特定的签名和结果类型,如§中所述7.16.3.这些方法可以是被查询对象的实例方法,也可以是对象外部的扩展方法,它们实现查询的实际执行.

您的具体示例描述为

带有第二个from子句后跟select子句的查询表达式

from x1 in e1
from x2 in e2
select v
Run Code Online (Sandbox Code Playgroud)

被翻译成

( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => v )
Run Code Online (Sandbox Code Playgroud)

因此,使用示例中的变量名称,任何xs具有方法的名称Treturned SelectMany(Func<Tx,Tys>, Func<Tx,Ty,Treturned>)都可以在语句中使用

Treturned returned =
    from x in xs
    from y in ys
    select r;
Run Code Online (Sandbox Code Playgroud)

这将完全编译时

Treturned returned = xs.SelectMany(x => ys, (x, y) => r);
Run Code Online (Sandbox Code Playgroud)

是的,这是xs上存在这种方法的任何时候.SelectMany存在的事实IEnumerable<>并不妨碍我们为其他类型配备具有相同名称的方法或扩展方法.

C#可以推断lambdas的类型,因为它知道什么xs是lambda ,并且从中可以查找类型为xss 的参数SelectMany.