在过去的几年中,f#已经发展成为微软完全支持的语言之一,使用了OCaml、ML和Haskell中孵化的许多思想。

在过去的几年里,c#通过引入越来越多的函数式语言特性扩展了它的通用特性:LINQ(列表理解)、Lambdas、闭包、匿名委托等等……

考虑到c#采用了这些函数特性,以及f#作为一种非纯函数语言的分类(它允许你访问框架库,或者当你想要调用函数时改变共享状态),这两种语言之间有很强的相似性,尽管每种语言都有自己截然相反的主要重点。

我感兴趣的是在你的多语言生产程序中使用这两种语言的任何成功模型,以及在生产软件(web应用程序,客户端应用程序,服务器应用程序)中,你在过去一年左右的时间里用f#写的东西,而你以前用c#写的东西。


不是个人经验,但你可以听一集DNR(我想是这个),他们和微软的人谈论f#。他们使用f#编写了大部分Xbox Live评分系统,这远非微不足道。该系统在数百台机器上大规模扩展,他们对此非常满意。


在微软研究院实习期间,我参与了Visual Studio IntelliSense for f#的部分工作(它本身就是用f#编写的)。我在早期的c#项目中已经有了一些智能感知的经验,所以我认为我可以比较这两者。

Visual Studio Extensibility is still based on COM, so you need to deal with objects that are not very nice .NET objects (and definitely not functional), but I don't feel there is any major difference between C# and F# (it works smoothly from F#) The data structures used to represent program code in F# are mostly discriminated unions (which are not supported in C# in any reasonable way) and this makes a huge difference for this kind of application (where you need to process tree structures, such as program code). Discriminated unions and pattern matching allows you to structure the code better (keep related functionality in one place rather than having it all over the place in virtual methods)

之前,我还为f#开发了CodeDOM提供程序(也是用f#编写的)。实际上,我首先用c#做了实验,但随后将代码转换为f#。

CodeDOM provider needs to traverse some structure represented using .NET objects, so there isn't much space for inventing your own representations of data (which is the area where F# can offer nice benefits). However, there were many small F# features that made the task easier. Since you need to produce a string, I defined custom operators for building strings (using StringBuilder) and implemented the code using them and higher-order functions (e.g. to format list of objects separated using the specified string etc.), which removed a lot of repetition (and tedious foreach loops).

这是两个相对具体的示例,但它们都与处理程序或表达式的表示有关,或者更一般地说,与复杂的树状数据结构有关。我认为在这方面,f#绝对是一个很好的选择(不管c#中的函数特性)。


f# Visual Studio组件的很多单元测试都是用f#编写的。它们在VS外部运行,模仿Visual Studio的各种功能。将实现接口的匿名对象组合起来的能力可以代替模拟框架/工具。我可以这样写

let owpe : string list ref = ref []
let vsOutputWindowPane = 
    { new IVsOutputWindowPane with
        member this.Activate () = err(__LINE__)
        member this.Clear () = owpe := []; 0
        member this.FlushToTaskList () = VSConstants.S_OK
        member this.GetName(pbstrPaneName) = err(__LINE__)
        member this.Hide () = err(__LINE__)
        member this.OutputString(pszOutputString) = owpe := pszOutputString :: !owpe ; 0
        member this.OutputStringThreadSafe(pszOutputString) = owpe := pszOutputString :: !owpe ; 0
        member this.OutputTaskItemString(pszOutputString, nPriority, nCategory, pszSubcategory, nBitmap, pszFilename, nLineNum, pszTaskItemText) = err(__LINE__)
        member this.OutputTaskItemStringEx(pszOutputString, nPriority, nCategory, pszSubcategory, nBitmap, pszFilename, nLineNum, pszTaskItemText, pszLookupKwd) = err(__LINE__)
        member this.SetName(pszPaneName) = err(__LINE__)
    }            
DoSomethingThatNeedsA(vsOutputWindowPane)
assert( !owpe = expectedOutputStringList )

当我需要一个实例,例如,一个IVsOutputWindowPane传递给一些其他组件,最终将调用OutputString和清除,然后检查字符串列表ref对象在测试结束,看看预期的输出是否被写入。


我不知道《the Path of Go》的AI是否正在制作中,但它是用f#编写的:

http://research.microsoft.com/en-us/events/techvista2010/demolist.aspx#ThePathofGo

The Path of Go: A Microsoft Research Game for Xbox 360 This demo showcases an Xbox 360 game, based on the game of Go, produced in-house at Microsoft Research Cambridge. Go is one of the most famous board games in East Asia, it originated in China 4000 years ago. Behind the deceptive simplicity of the game hides great complexity. It only takes minutes to learn, but it takes a lifetime to master. Although computers have surpassed human skills at Chess, implementing a competitive AI for Go remains a research challenge. The game is powered by three technologies developed at Microsoft Research Cambridge: an AI capable of playing Go, the F# language, and TrueSkill™ to match online players. The AI is implemented in F# and meets the challenge of running efficiently in the .net compact framework on Xbox 360. This game places you in a number of visually stunning 3D scenes. It was fully developed in managed code using the XNA environment.

(已经有人提到了“TrueSkill”。)


我们使用f#中的Lex-Yacc实现编写了一个自定义规则引擎语言

编辑以包括评论回复

c#中没有lex/yacc实现。(据我们所知,f#是)

这本来是可能的,但我们自己构建解析是非常痛苦的。

这个主题展示了一些其他的建议,比如外部库,但是我们的首席架构师是函数语言的老手,所以选择使用f#是很容易的。


在过去的6个月左右的时间里,我一直在为Visual Studio 2010开发Vim模拟层。这是一个免费的产品,所有的源代码都可以在github上免费获得

GitHub: http://github.com/jaredpar/VsVim VsVim在Visual Studio画廊

该项目分为3个DLL,代表一个不同的层。每一层都有一个相应的单元测试dll。

Vim引擎:f# 用于装饰和编辑器集成的WPF层:c# Visual Studio集成层:c#

这是我用f#做的第一个大项目,我不得不说我喜欢这门语言。在很多方面,我把这个项目作为学习f#的一种方法(如果你看看这个项目的历史,你会发现这个学习曲线非常明显)。

我发现f#最令人惊奇的是它是一种多么简洁的语言。Vim引擎包含了大部分的逻辑,但它只包含了整个代码库的30%。


我目前正在为一种编程语言编译。编译器完全是用f#编写的。编译器(除了用lex/yacc构建的lex和解析器)基本上是构建为一个复杂的树状结构的大量转换。

正如其他人所指出的那样,区别并集和模式匹配使得处理这种数据结构比将代码“到处”转储到虚拟方法中要容易得多。

在我开始编写编译器之前,我没有做过任何f#工作(然而,我在另一个OCaml变体中构建了编译器,称为MoscowML),正如Jared所说,从代码中可以看出我首先做了哪些部分,但总的来说,我发现f#很容易学习,在主要面向对象编码十年之后,再次进入FP思维模式,尽管需要更长一点的时间。

除了使用树,我发现编写声明性代码的能力是FP(包括f#)的主要好处,与c#描述我如何实现算法相比,有代码描述我试图实现的算法是一个巨大的优势。


我写了一个应用程序,以平衡国家发电计划的电站投资组合,以一个能源公司的交易位置。客户端和服务器组件用c#编写,但计算引擎用f#编写。

使用f#来解决这个应用程序核心的复杂性,清楚地展示了该语言在企业软件中的最佳位置,即大型数据集的算法复杂分析。我的经历是非常积极的。特别是:

我所工作的行业充斥着单位。我实现的方程(通常是几何性质的)涉及时间、功率和能量的单位。在测试和阅读/理解代码方面,让类型系统验证函数输入和输出单元的正确性可以节省大量时间。它根除了以前的系统容易出现的一整类错误。

与传统的编辑/编译/运行/测试循环相比,使用脚本文件和REPL (f# Interactive)可以让我在提交实现之前更有效地探索解决方案空间。对于程序员来说,这是建立他们对问题和设计张力的理解的一种非常自然的方式。

单元测试使用非副作用函数和不可变数据结构编写的代码对测试来说是一种乐趣。这里没有复杂的依赖于时间的交互来搞砸事情,也没有大量的依赖关系被嘲弄。

我在c#中定义了计算引擎的接口,并在f#中实现了计算。计算引擎可以被注入到任何需要使用它的c#模块中,而不需要考虑互操作性。无缝的。c#程序员永远不需要知道。

大量输入计算引擎的数据是向量和矩阵的形式。高阶函数以最小的麻烦和最少的代码把这些当作早餐。美丽。

函数式编程感觉很奇怪。我可以在一个算法上工作,努力让代码通过类型检查器,但一旦类型检查器满意,它就工作了。它几乎是二进制的,要么不会编译,要么是正确的。奇怪的边缘情况错误被最小化,递归和高阶函数删除了大量引入边缘情况错误的簿记代码。

并行性结果实现的功能纯洁性使得利用数据向量处理中固有的并行性变得成熟。也许这就是我接下来要做的,现在。net 4已经发布了。


我们发布了世界上第一个用f#编写的商业产品(f# for Visualization)和第二个(f# for Numerics),以及第一个关于f#的商业文献(the f#。NET Journal),并撰写并出版了关于f#当前版本的唯一一本书(Visual f# 2010 for Technical Computing)。

We had been shipping products along similar lines written in C# (e.g. this) but we also had a strong background in the commercial use of OCaml. We were enthusiastic early adopters of F# when it was still a research prototype back in 2006 because we recognised the potential of having a decent modern OCaml-like language on the industrial-strength .NET platform and, consequently, we pushed to have it productized. The result has been an incredible success and F# has far exceeded our lofty expectations.

For us, F# has many different advantages and we use it for a wide variety of applications. We have hundreds of thousands of lines of F# code in production. We now use F# for all of our LOB apps: our credit card transactions are processed using F# code, our product notifications are sent using F# code, our subscriptions are handled using F# code, our accounts are done using F# code and so on. Perhaps the main language feature that pays dividends here is pattern matching. We even used F# to color syntax highlight our latest book...

Our visualization library is a big seller and its functionality centers on F# interactive running in Visual Studio. Our library augments this with the ability to spawn interactive 2D and 3D visualizations with minimal effort (e.g. just Plot([Function sin], (-6., 6.)) to plot a sine wave). In particular, all threading issues are completely automated so users do not have to worry about UI threads and dispatch. First-class functions and laziness were extremely valuable when writing this part of the library and algebraic datatypes were used extensively elsewhere. Predictable performance also proved to be valuable here when our customers hit performance bugs in WPF's hit testing and were easily able to reimplement the relevant code in F# for a 10,000× performance improvement. Due to the free-form nature of this product's GUI, the GUI designer and C# would not have been beneficial.

Much of our work revolves around numerical methods, including both our commercial libraries and books. F# is much stronger in this area than C# because it offers high-level abstractions (e.g. higher-order functions) with minimal performance penalties. Our most compelling result in this context was the creation of a simple but generalized implementation of QR decomposition from linear algebra that was 20× shorter than the Fortran code from the reference implementation of LAPACK, up to 3× faster than the vendor-tuned Intel Math Kernel Library and more generic because our code can handle matrices of any type, even symbolic matrices!

目前,我们正在开发WPF/Silverlight组件,混合使用f#(用于guts)和c#(用于shim),构建WPF应用程序作为我们软件产品的交互手册,我正在写一本新书,多核f#,它将是。net上共享内存并行编程的权威指南。