将F#模块拆分为同一文件中的多个部分

将F#模块拆分为同一文件中的多个部分,f#,F#,我有以下工作F#源文件 namespace Namspa1 [<AutoOpen>] module M1 = let [<Literal>] constant1 = "Hello, " type Greeter(name) = member x.Greet() = sprintf "%s%s" constant1 name module M2 = let greet name = Greeter(name).Greet() const

我有以下工作F#源文件

namespace Namspa1

[<AutoOpen>]
module M1 = 
    let [<Literal>] constant1 = "Hello, "

type Greeter(name) = 
    member x.Greet() = sprintf "%s%s" constant1 name

module M2 =
    let greet name = Greeter(name).Greet()
  • constant1是一个值,因此必须位于模块内部
  • 因此,文件中的时间必须较晚;我希望它在名称空间中,而不是在模块中,因此它是非缩进的
  • 最后,greet是一个函数,所以它必须在一个模块中,我想使用相同的模块M1。它还使用Greeter,因此它必须位于类型定义之后
如果我尝试将greet函数定义更改为

module M1 =
    let greet name = Greeter(name).Greet()
我得到了M1的重复定义错误

我该怎么做

编辑

有人建议使用属性CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)修复重复定义错误,这是正确的,因此感谢您的帮助

然而,我的请求是关于扩展M1。我希望能够使用M1.greet,就好像函数是在M1中定义的一样。
例如,如果我尝试在外部使用定义(例如,另一个源文件),我可以使用M2.greet,因此我想使用M1.greet,这在属性中是不可能的,这可以通过将
compilementrepresentation
属性设置为。像这样扩展模块不是预期的用例,因此第二个模块定义需要移动到单独的源文件中

第一个文件:

namespace Namspa1

[<AutoOpen>]
module M1 = 
    let [<Literal>] constant1 = "Hello, "

type Greeter(name) = 
    member x.Greet() = sprintf "%s%s" constant1 name
名称空间Namspa1
[]
模块M1=
让[]constant1=“你好,”
类型迎宾员(姓名)=
成员x.Greet()=sprintf“%s%s”名称
第二个文件:

namespace Namspa1

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module M1 =
    let greet name = Greeter(name).Greet()
名称空间Namspa1
[]
模块M1=
让greet name=Greeter(name).greet()

从技术上讲,它会生成一个名为M1Module的模块,该模块将影响其他.NET语言的访问。

您可以使用。声明名称空间时,请注意
rec
关键字

namespace rec Namspa1

[<AutoOpen>]
module M1 =
    let [<Literal>] constant1 = "Hello, "
    let greet name = Greeter(name).Greet()

type Greeter(name) =
    member x.Greet() = sprintf "%s%s" constant1 name
namespace rec Namspa1
[]
模块M1=
让[]constant1=“你好,”
让greet name=Greeter(name).greet()
类型迎宾员(姓名)=
成员x.Greet()=sprintf“%s%s”名称

我需要重构
Greeter
以便它在构造函数中接受该常量值。为什么要将其行为与模块中的编译时常量耦合?为什么不直接内联这个常量呢?@Taylor Wood重构它的方法有很多,但我想知道是否有可能按照我的要求去做,或者这是编译器或语言的限制。此外,M1可以包含许多元素,而不仅仅是一个常量,这是一个简单的特别示例,用ModuleSuffix编译表示法清楚而简洁地说明了我的问题,M1.greet可以从其他F#源文件中访问。不过递归名称空间是一个更好的解决方案。@cadull我使用的是VS 2017,我只能从不同的文件访问M1.constant1,M1.greet只能在同一个文件中访问。如果我使用我的原始源代码,那么M2.greet也可以从不同的文件访问。我已经用一种变通方法更新了我的答案,但似乎不支持为此目的使用该功能。
namespace rec Namspa1

[<AutoOpen>]
module M1 =
    let [<Literal>] constant1 = "Hello, "
    let greet name = Greeter(name).Greet()

type Greeter(name) =
    member x.Greet() = sprintf "%s%s" constant1 name