2009-04-27 63 views
20

是否可以在文件间拆分F#模块?跨多个文件拆分F#模块

按照书上的我是,但是这本书可能是过时的 (F#基础)

+1

这个问题是一种误导,不清晰和http://stackoverflow.com/questions的DUP/172888/f-defined-and-using-a-type-module-in-the-the-project-in-the-the-project其中有更好的答案。国际海事组织,这是... – 2013-10-07 23:32:18

回答

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. 

更新:错误在F#4.0已经改变,它现:

错误FS0248:命名为“模块”两个模块发生在该组件的两个部分

其中Module是程序集的完全限定名称,包括名称空间部分。

+2

这是不好的,因为我正在做数据解析,并有许多不同的数据结构,所以我生成一个非常非常非常长的F#文件... – TimothyP 2009-04-27 14:01:31

+0

时间把它分解成常规的.NET类而不是模块?或者多个F#模块? – 2009-04-27 14:20:41

+3

不幸的是F#不支持部分类,所以你甚至不能在几个源文件中分割一个普通的.NET类。 – 2009-04-27 14:21:33

3

我有时在几个地方分割式,像这样:

module Foo 

type Partial = Bar | BarInt of int 

module Bar 

type Foo.Partial with 
    member x.Extend = 5 


let b = Foo.Bar.Extend 

其中模块Foo和酒吧都在不同的文件。

4

像库尔特说,你可以添加扩展方法类型,从而

// File1.fs 
namespace Foo 

type Mine() = 
    static member f1() =() 

然后

// File2.fs 
type Foo.Mine with 
    static member f2() =() 

Foo.Mine. // both f1 and f2 here 

因为它是一个类,而不是一个模块,你失去了做“开放的能力我的'(但获得超载的能力);因此这可能或可能不是您可以接受的替代方案,具体取决于您所做的事情。

6

类型的扩展很酷,并希望他们将允许跨文件,,而仍然是内部。如果您在同一个文件中执行类型扩展,它将编译为一个类,并且该扩展可以访问私有成员等。如果你在另一个文件中执行它,它只是一个“可选”扩展,就像C#静态扩展方法一样。 (尽管F#规格有所不同)。

如果仅在设计人员支持时未解决某些问题,我会感到惊讶。如果内部类型的扩展可能在程序集中的任何地方,那就很漂亮了。

另一种选择,你想要什么这可能不是,是创建一个类型和模块,调用模块相同的名称,然后添加ModuleSuffix标志它:

type Foo() = 
    static member Bar = 1 

[<CompilationRepresentationAttribute(CompilationRepresentationFlags.ModuleSuffix)>] 
module Foo = 
    let Baz = 2 

printfn "%d %d" Foo.Bar Foo.Baz 

这是用来在F#库中,所以它们可以有一个List类型或其他类型,以及模块中的大量辅助函数。

1

在我的一个项目中,我们的目标是将操作CpRm分开模块,但不要求用户为两个任务打开两个名称空间。

open Xake.FileTasks 
... 
do! Cp "*/*.exe" "deploy/*.exe" 
do! Rm "*/*.exe" 

我这里还有我的模块:

namespace Xake.FileTasks 

[<AutoOpen>] 
module RmImpl = 
    let Rm filemask target = 
... 

,另一种:

namespace Xake.FileTasks 

[<AutoOpen>] 
module CpImpl = 
    let Cp filemask target = 
...