c# - C# 中的 Monadic 理解语法

标签 c# haskell functional-programming monads

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

如果我理解正确的话,monadic comprehension 只是一种排序方式 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) => ...)

但即使这是真的,并且我们将 LINQ 视为 monad 理解语法,它仍然只适用于 IEnumerable<T> .我们在 C# 中确实有其他 monad,例如 Task<T> ,但我们如何在这些上使用 LINQ?

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

最佳答案

LINQ 查询语法只是语法糖,对 IEnumerable<> 一无所知,这就是为什么您可以将它用于其他用途的原因。

如果您检查 C# language specification ,在7.16.2节中描述了LINQ的查询表达式应该如何转换

The C# language does not specify the execution semantics of query expressions. Rather, query expressions are translated into invocations of methods that adhere to the query expression pattern (§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. 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.

您的具体示例描述为

A query expression with a second from clause followed by a select clause

from x1 in e1
from x2 in e2
select v

is translated into

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

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

这样的语句中
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# 可以根据它知道的事实推断 lambda 的类型 xs是,从中可以查找 xs 的参数类型的 SelectMany .

关于c# - C# 中的 Monadic 理解语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19709899/

相关文章:

c# - FileNotFoundException IIS7

haskell - Haskell 中的运算符 && 是否严格?

haskell - 当我在 Leksah 源代码编辑器中按空格键时,没有任何反应。我还缺少什么包?

scala - Scala 中具有尾函数的最大元素

recursion - 使用 LISP 递归查找列表中的元素位置

c# - 如何使用 C# 在运行时请求线程的锁和死锁?

c# - 在 C# 中,如何删除被另一个进程锁定的文件?

c# - Rfc2898DeriveBytes 的版本无关代码(在 .NET 4.0 上有 Dispose 但在 2.0 上没有)

haskell - 双胞胎的方法是什么?

recursion - 了解 Peter Norvig 在 PAIP 中的置换解决方案