"let f = fun a->"之间的区别F#中的a-1`和`let f a = a-1` [英] Difference between `let f = fun a -> a-1` and `let f a = a-1` in F#

查看:104
本文介绍了"let f = fun a->"之间的区别F#中的a-1`和`let f a = a-1`的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在F#中,let f = fun a -> a-1let f a = a-1之间有什么区别吗?据我所知,后者只是前者的语法糖.这是正确的吗?

In F#, is there any difference whatsoever between let f = fun a -> a-1 and let f a = a-1? As far as I can see, the latter is simply syntactic sugar for the former. Is this correct?

我在这里专门寻找语义的差异,而不是在任何特定的编译器处理这两种情况的方式上的差异.

I'm looking specifically for semantic differences here, rather than differences in how any particular compiler handles the two cases.

推荐答案

(fun a -> ...)只是一个匿名函数. F#与C#的不同之处在于,函数是一等公民,因此,当您将匿名函数绑定到f时,它将为f提供类型签名val f : int -> int(因为推断出aint32),就像您在第二个示例中绑定了普通的命名函数一样.您可以通过在F#交互式环境中运行示例来证明它们在语义上是相同的.

(fun a -> ...) is simply an anonymous function. F# differs from C# in that functions are first class citizens, so when you bind an anonymous function to f, it will give f the type signature val f : int -> int (because a is inferred to be int32), just as if you had bound a normal, named function as in your second example. You can prove that they are semantically identical by running your examples in F# interactive.

匿名函数甚至还支持泛型,这些泛型通常可以推断出来,但可以将其显式表示,如下所示:

Anonymous functions even support generics which are normally inferred but can be made explicit, like this:

let f<'T> = (fun (x: 'T) -> x)

摘自F#3.1规范草案(在此处找到):

Edit 2: From the F# 3.1 spec draft (found here):

如果值定义的直接右侧是匿名函数,则将其定义为函数定义,例如在本示例中:let f = (fun w -> x + w)

撇开明显的语法错误,这是说将函数值(即匿名函数)绑定到标识符实际上就等于普通函数定义.继续说,这种等效是函数式编程的主要内容",因此您可以肯定的是,将来这种情况不会改变.

Setting the obvious syntax error aside, what this is saying is that binding a function value (i.e. anonymous function) to an identifier is literally equivalent to a normal function definition. It goes on to say that this equivalence is a "staple of functional programming," so you can be pretty sure this won't change in the future.

出于一般目的,F#在设计时将函数定义和函数值(即委托实例,匿名函数)视为相等,但是当需要将函数定义提升为函数时值,它将使用委托类型FSharpFunc作为已编译类型.所有高阶函数(例如Array,List,Seq模块等)中都是这种情况,因为没有实际方法可以像使用委托一样使用CIL方法作为函数值.其他所有内容看起来都与您期望编译的C#或VB.NET完全一样-只是F#使用FSharpFunc的委托.

For general purposes, F# treats function definitions and function values (i.e. delegate instances, anonymous functions) as equal at design time, but when it needs to lift a function definition to a function value, it will use the delegate type FSharpFunc as the compiled type. This is the case for all higher order functions, like those in the Array, List, Seq modules, and so forth, since there's no actual way to use a CIL method as a function value like you can with delegates. Everything else looks exactly like you'd expect compiled C# or VB.NET to -- it's just delegates for which F# uses FSharpFunc.

我还不能添加注释,但是关于Tomas的答案,F#编译器不知道如何概括表达式let h = (); fun a -> a,但是如果添加类型注释,它将接受它.自己,就像尼康的id示例一样.

Edit 3: I'm not able to add comments yet, but with regards to Tomas' answer, the F# compiler doesn't know how to generalize the expression let h = (); fun a -> a but it will accept it if you add the type annotations yourself, like with Nikon's id example.

这是一张有关F#编译功能的简陋图片.请注意,Tomas的示例(他所​​称的排序表达式)如何变成FSharpFunc,而没有();的等效函数变成了实际的CIL方法.这就是上面的F#规范所讨论的.同样,当您将常规CIL方法用作值,带有部分应用程序或其他方式的值时,编译器将生成FSharpFunc以将其表示为闭包.

Edit 4: Here's an awesomely crude picture of how F# compiles functions. Notice how Tomas' example, a sequencing expression as he called it, gets turned into an FSharpFunc, whereas the equivalent function without the (); becomes an actual CIL method. This is what the F# spec was talking about above. Also, when you use a regular CIL method as a value, with partial application or otherwise, the compiler will make a FSharpFunc to represent it as a closure.

这篇关于"let f = fun a->"之间的区别F#中的a-1`和`let f a = a-1`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆