Tim*_*son 11
显然不是:
C:\temp\Tim>type 1.fs 2.fs
1.fs
#light
module Module
let sayHello1 = printfn "Hello, "
2.fs
#light
module Module
let sayHello2 = printfn "world!"
C:\temp\Tim>fsc 1.fs 2.fs
Microsoft F# Compiler, (c) Microsoft Corporation, All Rights Reserved
F# Version 1.9.6.2, compiling for .NET Framework Version v2.0.50727
2.fs(2,1): error FS0191: An implementation of the file or module Module has already been given.
Run Code Online (Sandbox Code Playgroud)
更新:F#4.0中的错误已更改,现在是:
错误FS0248:名为"模块"的两个模块出现在此程序集的两个部分中
其中Module是程序集的完全限定名称,包括名称空间部分.
类型扩展很酷,希望它们允许交叉文件,同时仍然是内在的.如果在同一文件中执行类型扩展,它将编译为一个类,并且扩展可以访问私有成员,依此类推.如果你在另一个文件中执行它,它只是一个"可选"扩展,如C#静态扩展方法.(即使F#规格说的不同.)
如果只是为了设计师的支持而在某些方面没有解决这个问题,我会感到惊讶.如果内部类型扩展可以在程序集中的任何位置,那将是非常光滑的.
另一个选项,可能不是你想要的,是创建一个类型和一个模块,调用模块相同的名称,然后添加ModuleSuffix标志:
type Foo() =
static member Bar = 1
[<CompilationRepresentationAttribute(CompilationRepresentationFlags.ModuleSuffix)>]
module Foo =
let Baz = 2
printfn "%d %d" Foo.Bar Foo.Baz
Run Code Online (Sandbox Code Playgroud)
这在F#库中使用,因此它们可以具有类型List或其他类型,以及模块中的大量帮助程序.
就像 Kurt 说的那样,您可以向类型添加扩展方法,从而
// File1.fs
namespace Foo
type Mine() =
static member f1 () = ()
Run Code Online (Sandbox Code Playgroud)
然后
// File2.fs
type Foo.Mine with
static member f2() = ()
Foo.Mine. // both f1 and f2 here
Run Code Online (Sandbox Code Playgroud)
因为它是一个类而不是一个模块,所以你失去了“打开我的”的能力(但获得了重载的能力);因此,这可能是也可能不是您可以接受的替代方案,具体取决于您在做什么。
在我的一个项目中,目标是放置文件操作Cp和Rm分离模块,但不需要用户为这两个任务打开两个命名空间。
open Xake.FileTasks
...
do! Cp "*/*.exe" "deploy/*.exe"
do! Rm "*/*.exe"
Run Code Online (Sandbox Code Playgroud)
这是我的模块:
namespace Xake.FileTasks
[<AutoOpen>]
module RmImpl =
let Rm filemask target =
...
Run Code Online (Sandbox Code Playgroud)
另一个:
namespace Xake.FileTasks
[<AutoOpen>]
module CpImpl =
let Cp filemask target =
...
Run Code Online (Sandbox Code Playgroud)