【问题标题】:About F# function关于 F# 函数
【发布时间】:2013-11-21 13:03:48
【问题描述】:

以下是我在 F# 编辑器中编写的函数,它按预期工作(答案:18)。

let quadruple x = x*2
let cal(u:int) = quadruple u + 10;
let result = cal 4

但是如果我改变代码的顺序,比如

let cal(u:int) = quadruple u + 10;
let quadruple x = x*2
let result = cal 4

我得到“未定义值或构造函数‘quadrule’”。从错误中,我认为失败是由于在声明之前调用了函数。对我来说,它有点像解释器风格。

问题:为什么会有这样的限制?这是为了保留一些兼容性问题吗?还是因为我没有定义任何模块/类?

【问题讨论】:

  • 在 F# 中,编译和定义顺序都很重要。我不知道这是什么原因(如果没有它,类型推断可能无法工作,或者工作效果不佳),但必须在使用它们的任何其他函数和/或模块的“上方”定义函数/模块。对于必须“向上”移动到可能引用它们的其他文件上方的完整文件也是如此。
  • @PatrykĆwiek,感谢您的评论。
  • @Nair:在代码中和项目结构中对依赖项进行建模是一件好事。在 C# 中,管理相互依赖性要困难得多,尤其是在大型项目中。
  • @Daniel,我猜你是说 F#
  • 不,我的意思是在 C# 中,它不强制依赖顺序,因此更难跟踪。我认为 F# 的方法是一种改进。

标签: f# f#-interactive f#-3.0


【解决方案1】:

尽管在惯用代码中所需的类型声明数量最少,但 F# 是一种静态强类型语言。这是可能的,因为编译器能够通过称为type inference 的过程明确推断类型。

简单地说,类型推断在 F# 中的处理方向是从上到下从左到右遍历代码。此因素会影响定义的文件内和文件间放置以及 F# 代码元素的使用。

将此原则应用于您的第二个 sn-p:当编译器第一次遇到第一行中的 quadruple 时,根据到目前为止解析的信息,对该元素的类型一无所知,可以消除它的歧义;这就是错误消息所传达的内容。

注意:在与OOP相关的F#领域与此原则有一定的偏差,在一定程度上允许在定义之前使用,例如Code属性在@987654325中的使用@类方法Double()下面,这里在属性定义之前使用:

type Sample() =
    member this.Double() = this.Code * 2
    member this.Code with get() : int = 3

对于类型推断工作的细粒度细节,最好的检查位置是F# Language Specification

【讨论】:

    猜你喜欢
    • 2017-08-23
    • 2017-02-27
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多