SelectMany
在 C# 中对应于 Haskell(>>=)
或flatMap
Scala 中的绑定。Haskell 中的签名>>=
是:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
所以 bind 是一种用于从另一个构造一个单值的操作。
在 C# 的情况下,m
上面的签名是IEnumerable
,IObservable
等IQueryable
。对于IEnumerable
,SelectMany
是
IEnumerable<A> -> (A -> IEnumerable<B>) -> IEnumerable<B>
或在 C# 中
public static IEnumerable<B> SelectMany<A, B>(this IEnumerable<A> first, Func<A, IEnumerable<B>> selector)
bind 的含义取决于 monad 类型,对于 IEnumerable,输入序列中的每个元素都用于创建一个新序列,将得到的序列序列展平以产生输出序列。
绑定的另一种表述可以使这一点更清楚。虽然 monad 通常根据它们的 bind 实现来描述,但 monad 还必须支持另外两个操作,map
和join
.
map
对应于 C# 中的 Select ,如下所示:
map :: Monad m => (a -> b) -> (ma -> m b)
所以这是一种将常规函数提升到一元值之上的“结构保持”方式。
join
有类型
join :: Monad m => m m a -> m a
所以 join 用于扁平化嵌套的一元值。在 C# 中,这看起来像
public static IEnumerable<A> Join<A>(this IEnumerable<IEnumerable<A>> nested)
bind
可以根据 map 和 join as 来实现
m >>= f = join (map f m)
所以要回答原始问题,SelectMany
对应bind
或flatMap
用其他语言。Bind 不仅仅是展平,还可以看作是一种转换,然后是嵌套的单子值(例如 的情况下的序列IEnumerable<T>
)的展平。join
forIEnumerable<T>
在当前的 linq 扩展中不存在。