2011-01-13 40 views
23

我用C#写了一些使用LINQ的查询。过了一段时间,我开始使用Haskell,它是一种函数式编程语言(一种不太流行的语言),对我来说,它们似乎都是几乎相同的东西。但我不确定这一点。请问,如果有人比我更多地使用它们,他们能否告诉我他们在编程原则方面是否差不多?Haskell和LINQ之间有任何连接吗?

此外,可以将LINQ视为功能性编程吗?

谢谢。

+0

Huskell?从来没有听说过。但是我听说过Haskell。 – 2011-01-13 18:09:55

+6

@Etienne de Martel Huskell是Haskell咖喱的双胞胎兄弟,他解决了Löb的悖论;) – 2011-01-13 18:11:55

+1

不,他们不是“同一件事”。甚至没有远程。但据我所知,LINQ的灵感来自于Haskellers发明的一个特别巧妙的技巧(就像列举理解一般为几个/所有单子一样,从来没有把它变成一个标准)。 – delnan 2011-01-13 18:14:53

回答

54

对我来说,他们似乎都是几乎相同的东西。但我不确定这一点。请问,如果有人比我更多地使用它们,他们能否告诉我他们在编程原则方面是否差不多?

是的,LINQ查询解析的设计深受Haskell设计的影响。当我们设计LINQ时,Haskell专家Erik Meijer在C#语言设计委员会工作;他的见解非常有价值。 (在这个过程结束时我加入了设计团队,很遗憾,我没有参与所有有趣的曲折,多年来设计经历了一段时间;它开始比传统OO更为传统!)

如果您最近对Haskell进行了认真的探索,那么您可能已经熟悉monad的想法。 LINQ语法专门用于使序列monad上的操作感觉自然,但实际上实现更一般; C#所谓的“SelectMany”是对任意monad上的“绑定”操作稍作修改的形式。实际上,您可以使用任何monad的查询理解,as my colleague Wes describes here,但这样做看起来很奇怪,我建议在生产代码中使用它。

此外,可以将LINQ视为函数式编程吗?

是的,LINQ受到函数式编程思想的很大影响。它旨在将功能视为一流的对象,强调对副作用的计算等等。

1

也可以考虑LINQ 函数式编程?

LINQ意味着一种功能样式,因为它类似于例如原则上只读的SQL select。但是,因为.NET中的LINQ子句是由普通的CLR例程实现的,所以没有什么可以阻止LINQ表达式修改状态。另一方面,Haskell是一种“纯”功能语言,因此表达式不能修改全局状态。尽管可以执行IO和图形操作,但是这些操作可以使用与.NET中的任何东西非常不同的方式来执行,包括F#,它可以让您以某种程度上透明的方式进入程序风格。

8

看看Erik Meijer Lecture可能是值得的。这是它的描述。

我们揭开序幕C9讲座与旅程 到功能 编程的世界函数式语言 纯粹和拉姆达 演算的大祭司,埃里克·梅杰博士(你可以 感谢埃里克许多的功能 构造已经在 语言如C#和VB.NET中显示。当您使用LINQ时,感谢Erik以及 Anders)。

3

确实,C#已经获得了函数式编程的某些方面。首先是lambda语句,作为匿名代理实现。您现在不再需要将方法定义为属于某个对象,并且可以使用与其他变量类似的方式定义一个方法。这使得许多功能型结构:

var mult = (a,b)=>a*b; 
var square = (a)=>Math.Pow(a,2); 
var multandsquare = (a,b)=>square(mult(a,b)); 

//None of the above give a lick about what a and b really are, until... 
multandsquare(5,3); //== 225 

函数式编程的基本模式 - 基本上任何你可以告诉电脑做可以在高阶功能方面被告知 - 可以应用到C#程序,特别是现在C#实际上拥有更高阶的函数。编译器会迫使你至少有一个类至少有一个公共main方法(这就是OO的工作方式),但从这一点来说,你只能根据函数定义几乎所有的东西(def:“方法”的子类,取N个参数并产生1个没有“副作用”的输出)实例化为lambda表达式。

Linq确实有一些功能结构。基本上,它的方法链范例是一元处理的一个例子,它是通过函数式语言(现在用C#)操作封装来构造操作序列的。在IEnumerable上调用Linq方法会返回另一个IEnumerable,它实际上是一个不同的具体类,它包含源Enumerable和一些要执行的lambda的句柄。您可以非常简单地以功能语言复制它;它是源的元组(它本身就是当前元素的元组和其他所有元素)以及执行它的函数,它将源元组转换为结果,每次一个元素(在Linq中,它将在函数中实现语言,是将某些操作嵌套到定义的“汇总”功能中)。调用必须产生实际答案的方法(具体的类型化结果),并且所有这些函数都被充分评估以产生期望的结果。