简体   繁体   English

C#中的Monadic理解语法

[英]Monadic comprehension syntax in C#

I've been hanging out in a #haskell IRC room a couple of days ago and someone mentioned that C# has syntax for doing monadic comprehension . 几天前我一直在#haskell IRC房间里闲逛,有人提到C#具有进行monadic理解的语法。 What does this mean? 这是什么意思?

If I understand correctly, monadic comprehension is just a way of sequencing bind operations, which kind of sounds like a do notation? 如果我理解正确的,一元的理解仅仅是一个排序的方式bind操作,哪一种听起来像一个do记号? Is that correct? 那是对的吗?

The problem is that I don't see this in C#. 问题是我在C#中没有看到这个。 As far as I know IEnumerable<T> is a monad where SelectMany is its bind function, as its signature is A -> IEnumerable<B> . 据我所知, IEnumerable<T>是一个monad,其中SelectMany是它的bind函数,因为它的签名是A -> IEnumerable<B> With a little stretch of imagination, we can do 只需一点想象力,我们就可以做到

from x in xs
from y in ys

which translates into ( I'm not 100% sure here ) 这转化为( 我不是100%肯定在这里

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

But even if this is true and we think of LINQ as a monad comprehension syntax, it still only applies to IEnumerable<T> . 但即使这是真的,我们将LINQ视为monad理解语法,它仍然只适用于IEnumerable<T> We do have other monads in C# like Task<T> , but how can we use LINQ on those? 我们在C#中有其他monad,比如Task<T> ,但我们怎样才能在那些上使用LINQ?

It is possible that many of the assumptions in this question are completele wrong, as I'm still trying to grasp some of the monad magic stuff. 这个问题中的许多假设可能是完全错误的,因为我仍然试图掌握一些monad神奇的东西。 Please correct me if I'm wrong :) 如果我错了请纠正我:)

LINQ query syntax is merely syntactic sugar, and doesn't know anything about IEnumerable<> , which is why you can use it for other things. LINQ查询语法只是语法糖,并且对IEnumerable<>一无所知,这就是为什么你可以将它用于其他事情。

If you check the C# language specification , it describes how LINQ's query expressions should be transformed in section 7.16.2 如果检查C#语言规范 ,它将描述如何在7.16.2节中转换LINQ的查询表达式

The C# language does not specify the execution semantics of query expressions. C#语言未指定查询表达式的执行语义。 Rather, query expressions are translated into invocations of methods that adhere to the query expression pattern (§7.16.3). 相反,查询表达式被转换为符合查询表达式模式(第7.16.3节)的方法的调用。 Specifically, query expressions are translated into invocations of methods named Where, Select, SelectMany, Join, GroupJoin, OrderBy, OrderByDescending, ThenBy, ThenByDescending, GroupBy, and Cast.These methods are expected to have particular signatures and result types, as described in §7.16.3. 具体来说,查询表达式被转换为名为Where,Select,SelectMany,Join,GroupJoin,OrderBy,OrderByDescending,ThenBy,ThenByDescending,GroupBy和Cast的方法的调用。这些方法应具有特定的签名和结果类型,如§中所述7.16.3。 These methods can be instance methods of the object being queried or extension methods that are external to the object, and they implement the actual execution of the query. 这些方法可以是被查询对象的实例方法,也可以是对象外部的扩展方法,它们实现查询的实际执行。

Your specific example is described as 您的具体示例描述为

A query expression with a second from clause followed by a select clause 带有第二个from子句后跟select子句的查询表达式

from x1 in e1
from x2 in e2
select v

is translated into 被翻译成

( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => v )

So, using the variable names from your example, any xs that has a method Treturned SelectMany(Func<Tx,Tys>, Func<Tx,Ty,Treturned>) can be used in a statement like 因此,使用从实施例中的变量名,任何xs具有方法Treturned SelectMany(Func<Tx,Tys>, Func<Tx,Ty,Treturned>)可以在类似语句中使用

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

This will compile exactly when 这将完全编译时

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

does, which is any time such a method exists on xs. 是的,这是xs上存在这种方法的任何时候。 The fact that SelectMany exists for IEnumerable<> doesn't prevent us from equiping other types with methods or extension methods with the same name. 对于IEnumerable<>存在SelectMany的事实并不妨碍我们为其他类型配备具有相同名称的方法或扩展方法。

C# can infer the types for the lambdas from the fact that it knows what xs is, and from that can look up the types to the arguments of xs 's SelectMany . C#可以从它知道xs是什么的事实推断lambdas的类型,并且从中可以查找xsSelectMany参数的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM