F#函数与C#"Func"tions

Bil*_*one 15 c# f#

所以我遇到了这个F#之旅:https://docs.microsoft.com/en-us/dotnet/articles/fsharp/tour

...和男孩你好F#有趣!游览的一开始就定义了一个示例函数,它看起来非常简单:

/// You use 'let' to define a function. This one accepts an integer argument and returns an integer. 
/// Parentheses are optional for function arguments, except for when you use an explicit type annotation.
let sampleFunction1 x = x*x + 3
Run Code Online (Sandbox Code Playgroud)

所以这对我来说很有意义.它定义了函数是什么,所以如果我将一些数字传递给这个东西,它会对它进行平方并为该结果增加3,如巡视中的下一行所示:

 /// Apply the function, naming the function return result using 'let'. 
/// The variable type is inferred from the function return type.
let result1 = sampleFunction1 4573
Run Code Online (Sandbox Code Playgroud)

经过几分钟的思考后,我得出结论,C#也可以做到这一点!我确实非常喜欢C#.就我所知,这就是上面在C#中的样子:

        Func<int, int> sampleFunction1 = x => x*x + 3;
        var result = sampleFunction1(4573);
Run Code Online (Sandbox Code Playgroud)

所以我的主要问题是,我在C#中写的内容与F#tour给我的内容有什么区别?子问题是:IL代码是否有任何不同,即使它是相同的CLR?我会使用F#而不是C#的几个原因是什么?

Fyo*_*kin 28

从技术上讲,这些是等价的.IL可能有点不同,只是因为这些是不同的编译器,但并不多.实质上,这些是以相同的方式编译的.

但是C#不能做到精确地说.你有没有注意到你必须Func<int,int>在前面写作?但这只是一个非常小的玩具功能.在更实际的情况下会发生什么?注意:

// F#
let f x m = Map.find (x, x+1) m |> Seq.map ((+) 1)

// C#
Func<int, IDictionary<Tuple<int, int>, IEnumerable<int>>, IEnumerable<int>> f = (x, m) => m[Tuple.Create(x, x+1)].Select( i => i+1 );
Run Code Online (Sandbox Code Playgroud)

好玩,不是吗?
这称为"类型推断".如同,F#能够根据使用的东西推断出类型的东西.你几乎可以写一个完整的程序,从来没有使用过类型注释.C#在某种程度上也有这个.这就是我能够调用的方式.Select( i => i+1 ),而C#知道这iint,因为之前.Select发生的事情是IEnumerable<int>.但它非常有限,而不是那么强大.

类型推断仅仅是一个的F#的诸多好处.我选择了它,因为你看着它并没有看到它.但还有更多.编译顺序,缺少空值,默认不变性,代数数据类型,自动currying和部分应用......实际上,还要比SO答案更合适.

那些希望发现精彩和令人兴奋的函数式编程世界的人,特别是F#,我通常会直接发送到https://fsharpforfunandprofit.com/,进入Wlaschin先生亲切而有能力的人手中.一个美妙的资源,阅读所有.

  • 好吧,我不能只将http://fsharpforfunandprofit.org的全部内容复制并粘贴到答案中.不得不选择一些东西. (5认同)
  • 不多.它会使类型符号更短,但你仍然需要写它.使用C#的东西,无论它获得多少闪亮的功能,你都无法修复一些基本问题(例如空值,可变性)而不会破坏旧代码.如果你打破旧代码,那么这是一种新语言,在这种情况下你也可以转向F#. (4认同)
  • 我认为部分应用在答案中应该得到更多的报道.纯粹的意外是OP使用`let sampleFunction1 x = ...`而不是`let sampleFunction1 xy = ...`作为例子,并且与后者相当的C#将是`Func <int,Func <int, int >>`而不是`Func <int,int,int>`绝对是值得注意的,至少可以说. (3认同)
  • 我注意到巡演中的不变性,我非常喜欢!我也喜欢你的例子,看看f#在f#中有多糟糕.你对C#7中新的元组内容如何改变有什么见解吗? (2认同)