在哪些方面,F#的使用比C#更合适?

时间:2010-05-06 22:45:11

标签: c# f#

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

在过去几年中,C#通过引入越来越多的功能语言功能扩展了它的通用功能:LINQ(列表理解),Lambdas,闭包,匿名代表等......

鉴于C#采用这些功能特性和F#的分类法作为一种不纯的函数式语言(它允许您在调用函数时访问框架库或更改共享状态),尽管这两种语言之间存在很强的相似性,每个都有自己的极性相反的主要重点。

我对在您的制作多语言程序中使用这两种语言的任何成功模型以及您在过去一年中用F#编写的生产软件(网络应用程序,客户端应用程序,服务器应用程序)中的区域感兴趣以前会用C#编写。

11 个答案:

答案 0 :(得分:256)

我已经编写了一份申请,以平衡发电站组合的国家发电计划与能源公司的交易位置。客户端和服务器组件在C#中,但计算引擎是用F#编写的。

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

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

探索性编程使用脚本文件和REPL(F#Interactive)使我能够在提交实现之前更有效地探索解决方案空间,而不是更传统的编辑/编译/运行/测试循环。对于程序员来说,建立他们对问题的理解以及游戏中的设计紧张是一种非常自然的方式。

单元测试使用非副作用函数和不可变数据结构编写的代码是一种测试的乐趣。没有复杂的时间依赖性交互可以搞砸或者需要模拟大量的依赖关系。

互操作我在C#中定义了计算引擎的接口,并在F#中实现了计算。然后可以将计算引擎注入任何需要使用它的C#模块,而不用担心任何关于互操作性的问题。无缝。 C#程序员不需要知道。

代码缩减输入计算引擎的大部分数据都是向量和矩阵的形式。更高级的功能在早餐吃这些,最小的代码。美丽。

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

并行性最终实现的功能纯度使得在处理数据向量中利用固有的并行性成熟。也许这就是我现在要去的地方,因为.NET 4已经出局了。

答案 1 :(得分:76)

在Microsoft Research实习期间,我参与了F#的Visual Studio IntelliSense的一些部分(它本身是用F#编写的)。我已经从早期的C#项目中获得了一些IntelliSense的经验,所以我想我可以比较两者。

  • Visual Studio Extensibility仍然基于COM,所以你需要处理不是很好的.NET对象的对象(绝对没有功能),但我觉得C#之间没有任何重大区别和F#(它从F#顺利运作)

  • 用于表示F#中程序代码的数据结构主要是区分的联合(C#中不支持任何合理的方式),这使得巨大这种应用程序的区别(您需要处理树结构,例如程序代码)。歧视的联合和模式匹配允许您更好地构建代码(在一个地方保留相关的功能,而不是在虚拟方法中将它们全部放在一起)

之前,我还为F#的CodeDOM提供程序工作(也用F#编写)。我实际上是在C#中进行了第一次实验,但后来将代码转换为F#。

  • CodeDOM提供程序需要遍历使用.NET对象表示的某些结构,因此没有太多空间来发明您自己的数据表示(这是F#可以提供很好的好处的区域)。

  • 然而,有许多小F#功能使任务更容易。由于您需要生成一个字符串,我定义了构建字符串的自定义运算符(使用StringBuilder)并使用它们和更高阶函数实现代码(例如,格式化使用指定字符串分隔的对象列表等),这删除了很多重复(和繁琐的foreach循环)。

这是两个相对具体的示例,但它们都与使用程序或表达式的表示相关,或者更一般地说,与复杂的树状数据结构相关。我认为在这个领域,F#绝对是一个不错的选择(无论C#的功能如何)。

答案 2 :(得分:42)

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

我们一直在使用C#编写的类似产品(例如this)运送产品,但我们在OCaml的商业用途方面也有很强的背景。早在2006年它仍然是研究原型时,我们是F#的早期采用者的热心,因为我们认识到在工业级.NET平台上拥有类似现代OCaml语言的潜力,因此,我们推动其产品化。结果取得了令人难以置信的成功,F#远远超出了我们的崇高期望。

对于我们来说,F#有许多不同的优点,我们将它用于各种各样的应用程序。我们生产了数十万行F#代码。我们现在将F#用于所有我们的LOB应用程序:我们的信用卡交易使用F#代码处理,我们的产品通知使用F#代码发送,我们的订阅使用F#代码处理,我们的帐户使用F#代码等。也许支付红利的主要语言特征是模式匹配。我们甚至用F#来着色语法突出我们最新的书......

我们的可视化库是一个大卖家,其功能集中在Visual Studio中的F#交互式运行。我们的库增强了这一功能,能够以最小的努力产生交互式2D和3D可视化(例如,仅Plot([Function sin], (-6., 6.))绘制正弦波)。特别是,所有线程问题都是完全自动化的,因此用户不必担心UI线程和调度。在编写库的这一部分时,一流的函数和惰性非常有价值,而代数数据类型在其他地方被广泛使用。当我们的客户在WPF的热门测试中遇到性能缺陷并且能够轻松地重新实现F#中的相关代码以实现10,000×性能改进时,可预测的性能也证明是有价值的。由于该产品的GUI具有自由形式的特性,因此GUI设计人员和C#不会有所帮助。

我们的大部分工作都围绕数值方法展开,包括我们的商业图书馆和书籍。 F#在这个领域比C#强得多,因为它提供了高级抽象(例如高阶函数),而且性能损失最小。在这种情况下,我们最引人注目的结果是从线性代数中创建了一个简单但通用的QR分解实现,比LAPACK的参考实现中的Fortran代码短20倍,比供应商调整的Intel Math快3倍。内核库更通用,因为我们的代码可以处理任何类型的矩阵,甚至是符号矩阵!

我们目前正在开发混合了F#(用于胆量)和C#(用于垫片)的WPF / Silverlight组件,构建WPF应用程序作为我们软件产品的交互式手册,我正在编写一本新书,多核F#,这将是.NET上共享内存并行编程的权威指南。

答案 3 :(得分:25)

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

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

  1. Vim引擎:F#
  2. 用于装饰和编辑器集成的WPF层:C#
  3. Visual Studio集成层:C#
  4. 这是我用F#做过的第一个重大项目,我不得不说我喜欢这种语言。在很多方面,我使用这个项目作为学习F#的方法(如果你仔细研究项目的历史,这个学习曲线非常明显)。

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

答案 4 :(得分:13)

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传递给最终将调用OutputStringClear的其他组件,然后在测试结束时检查string list ref对象以查看是否需要输出写了。

答案 5 :(得分:9)

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

编辑以包含评论回复

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

这本来是可能的,但是自己构建解析是一种彻头彻尾的痛苦。

This topic显示了一些其他建议,例如外部库,但我们的首席架构师是函数式语言的老手,所以选择使用F#是不费脑筋的。

答案 6 :(得分:7)

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

正如其他人所指出的那样,区分联合和模式匹配使得使用这种数据结构比在“无处不在”的虚拟方法中转储代码要容易得多

在我开始编写编译器之前,我还没有完成任何F#工作(不过我在另一个名为MoscowML的OCaml变体中编译了编译器)正如Jared所说,从代码中可以看出我先做了哪些部分,但总的来说我发现F#很容易学习,在编写主要OO十年之后再次进入FP思维集会花费更长的时间。

除了使用树之外,我发现能够编写声明性代码FP的主要好处(包括F#),其代码描述了我试图实现的算法,而不是C#描述我是如何实施algortihm是一个巨大的优势。

答案 7 :(得分:6)

不是个人经历,但你可以听一集DNR(我认为是this one),他们会与微软民众谈论F#。他们使用F#编写了大部分Xbox Live评分系统,这个系统远非微不足道。该系统在数百台机器上大规模扩展,并且非常满意。

答案 8 :(得分:6)

WebSharper人已经构建了一个以F#为中心的整个产品,用于Web编程。这是一篇谈论它的文章:

http://www.sdtimes.com/content/article.aspx?ArticleID=34075

答案 9 :(得分:6)

以下是一个关于银行使用F#和C ++ / COM的案例研究:

http://www.microsoft.com/casestudies/Case_Study_Detail.aspx?CaseStudyID=4000006794

答案 10 :(得分:5)

我不知道它是否正在制作中,但是“走的路”的AI是用F#编写的:

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

  

Go的路径:微软研究院   适用于Xbox 360的游戏

     

这个演示展示了一个Xbox 360游戏,   基于Go游戏,制作   微软研究院的内部人员   剑桥。围棋是其中之一   它在东亚着名的棋盘游戏   起源于4000年前的中国。   在欺骗性的简单性的背后   游戏隐藏着极大的复杂性。它只是   需要几分钟才能学习,但需要花费一些时间   一生要掌握。电脑虽然   在国际象棋中超越了人类的技能,   为Go实施竞争性AI   仍然是一项研究挑战。游戏   由三种技术提供支持   在微软研究院开发   剑桥:一个能够上场的AI   Go,F#语言和TrueSkill™   匹配在线玩家。人工智能是   在F#中实现并满足   有效运行的挑战   Xbox上的.net紧凑框架   360.这个游戏让你进入一些视觉上令人惊叹的3D场景。它是   完全使用托管代码开发   XNA环境。

(其他人已经提到过“TrueSkill”。)