F# 中模块和命名空间之间的区别

Posted

技术标签:

【中文标题】F# 中模块和命名空间之间的区别【英文标题】:DIfference between Modules and Namespaces in F# 【发布时间】:2011-06-26 00:46:59 【问题描述】:

我在理解 F# 中的模块和命名空间之间的确切区别以及使用其中一个或另一个时遇到了问题。 好吧,它们都是为了封装代码并定义层次结构以使我们的项目井井有条。

模块有很多特性:它们可以包含各种值、类型,这些元素也可以定义为publicprotectedinternal

但是,当使用模块时呢?

我还了解到,模块最终被映射为 MSIL(中间语言)中的类。所以一个模块是一个类,是一个类型...... 我的疑虑有所改善....

当使用模块时??? 它们有用吗?

D. Syme 还认为模块是可扩展的,所以我认为从这个角度来看它们就像命名空间。

我无法理解使用它们的原因。

谢谢

【问题讨论】:

【参考方案1】:

一个主要区别:

.NET 命名空间不能保存 (let 定义),而模块可以。

在 IL/字节码级别,模块被编译为 .NET 类,而不是 .NET 命名空间。

何时使用模块?

对于小而具体的任务,F# 和其他 FP 通常遵循自下而上编程的模式:将任务分解为一组小函数,然后将这些函数分组为一个模块。

答案是使用模块将一组相关函数和其他 F# 值和类型组合在一起是很自然的。

虽然命名空间用于对更大的事物进行分组:例如矩阵运算的所有类。

模块不是静态类(在 C# 意义上) 模块可以保存特殊的 F# 值,例如咖喱函数;而静态类则不能。

【讨论】:

@Yin,您能否提供一个参考来说明“模块被编译为 .NET 类”?谢谢。 @Thr4wn 我用.net反射器看c#版本的代码。【参考方案2】:

正如殷竹所说,模块可以保存值。您可以打开命名空间等模块。这两个特性结合在一起就是为什么在 F# 中你可以做类似的事情

let z = max x y

而在像 C# 这样的语言中,你总是不得不说类似的话

var z = Math.Max(x,y)
//      ^^^^^   can't call methods from elsewhere without a qualifier

并使用限定名称 (SomeClass.Method) 而不仅仅是名称 (letBoundFunction)。因此,当您希望人们能够打开您的模块 Foo 并调用 bar 时,您可以使用模块,只需在任何地方说 bar 而不是 Foo.bar。 (这对运算符特别有用,例如,如果您在库中定义了一堆用户定义的运算符(例如+++ 或诸如此类),通过将它们放入模块中,人们可以打开模块然后使用例如@ 987654330@ 而不是像(Foo.+++) x y 之类的繁琐东西。)

请注意,虽然 F# 默认将代码放在模块中的 .fs 文件中(使用文件名),但您可以通过将文件中的第一个代码作为命名空间声明来更改此设置,例如

namespace Yadda
// declare some types or whatnot, they go in namespace Yadda

或者通过声明你自己的模块

module Blah
// stuff goes in Blah module

在文件的顶部。

【讨论】:

谢谢布赖恩,你真的很有帮助 不得不否决这个历史性答案,因为它不再正确。从 C# 6 开始,静态 using 语句可用于允许 C# 代码,如 var z = Max(x,y)

以上是关于F# 中模块和命名空间之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

JSDoc:模块和命名空间之间的关系是啥

F#、命名空间、模块、fs 和 fsx

“使用命名空间标准”和“命名空间标准”之间的区别?

“使用 MyNameSpace;”之间的区别和“命名空间 MyNameSpace”

XML中命名空间之间的区别

命名空间,类,对象和实例之间有什么区别?