【发布时间】:2011-02-27 17:23:42
【问题描述】:
我正在阅读 Real-world functional programming by Tomas Petricek and Jon Skeet 的书,我很难消化关于计算表达式的部分1)(又名 monads)。
通过这本书,我了解到——与我之前的经验相反——LINQ 查询表达式不限于IEnumerable<T>,还可以用于其他自定义类型。 这看起来很有趣对我来说,我想知道是否存在查询表达式语法 (from x in ... select ...) 非常适合的场景。
一些背景信息:
显然,这种自定义类型被称为计算类型,它们被描述为与monads in Haskell 本质上相同的东西。我一直无法理解 monad 到底是什么,但根据书上的说法,它们是通过称为 bind 和 return 的两个操作来定义的。
在函数式编程中,这两个操作的类型签名将是(我认为):
// Bind : M<A'> -> (A' -> B') -> M<B'>
//
// Return : A' -> M<A'>
其中M 是一元类型的名称。
在 C# 中,这对应于:
Func< M<A>, Func<A,B>, M<B> > Bind;
Func< A, M<A> > Return;
事实证明,LINQ 的Enumerable.Select(投影运算符)与M := IEnumerable 的绑定操作具有完全相同的签名。
我的自定义 LINQ 计算类型:
利用这些知识,我现在可以编写自定义计算类型 not IEnumerable:
// my custom computation type:
class Wrapped<A>
{
// this corresponds to the Return operation:
public Wrapped(A value)
{
this.Value = value;
}
public readonly A Value;
}
static class Wrapped
{
// this corresponds to the Bind operation:
public static Wrapped<B> Select<A, B>(this Wrapped<A> x, Func<A,B> selector)
{
return new Wrapped<B>(selector(x.Value));
}
}
现在我可以在 LINQ 查询表达式中使用Wrapped<T>,例如:
Wrapped<int> wrapped = new Wrapped<int>(41);
Wrapped<int> answer = from x in wrapped // works on int values instead
select x + 1; // of Wrapped<int> values!
当然,这个例子不是很有用,但它演示了如何查询表达式可以做其他事情而不是使用集合,例如用某种类型包装和展开值。
问题:
上面的计算类型似乎不是很有用。因此我想知道,利用 LINQ 查询表达式还有哪些其他合理的用途(除了处理集合)?
1) 第 12.4 节:“引入替代工作流程”,从第 334 页开始。
【问题讨论】:
-
顺便说一句,这个问题应该是社区维基吗?
-
刚刚在 monads 上找到了另一个答案(由 Eric Lippert 撰写),我觉得非常有用:stackoverflow.com/questions/2704652#2704795
-
顺便说一句:这里的“绑定”类型错误:这是 Haskell 中
fmap的签名,或者只是列表中的map,这确实是Select()所做的。更有趣的一元绑定是Func<M<A>, Func<A,M<B>>, M<B>>。这是列表上的concatMap,或者等效地是IEnumerable上的SelectMany()。你写的 identity monad 仍然不会做任何有趣的事情,但是在一个更有趣的 monad 中,所有有趣的事情都会发生在SelectMany中。试试 Maybe monad —— 那是“一个包装的值或一个空对象”。 -
@camccann: 感谢您指出正确的类型签名。实际上,在发布后不久我就想到我弄错了
Bind。 -- 我确实实现了Maybemonad btw.,并且惊叹于您如何在 LINQ 查询表达式中获得条件评估/执行之类的东西(取决于Maybe值是否包含值)。但这是唯一一个或多或少适合 LINQ 并做一些明智的事情的有趣 monad。你知道更多与from..in..where..let..selectLINQ 语法完美结合的 monad 吗?
标签: c# linq ienumerable monads computation-expression