跨多个文件拆分F#模块

Tim*_*hyP 27 .net f# module

是否可以跨文件拆分F#模块?

根据我所拥有的那本书,但这本书可能已经过时了(F#的基础)

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是程序集的完全限定名称,包括名称空间部分.

  • 不幸的是,F#不支持部分类,因此您甚至无法将常规.NET类拆分为多个源文件. (3认同)
  • 这很糟糕,因为我正在进行数据解析,并且有许多不同的数据结构,因此我生成了一个非常非常长的F#文件...... (2认同)

Mic*_*lGG 7

类型扩展很酷,希望它们允许交叉文件,同时仍然是内在的.如果在同一文件中执行类型扩展,它将编译为一个类,并且扩展可以访问私有成员,依此类推.如果你在另一个文件中执行它,它只是一个"可选"扩展,如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或其他类型,以及模块中的大量帮助程序.

  • 这在F#中很简洁,但如果我想通过反射从外部访问这些类型,它们会出现类型"Foo"和"FooModule".基于已接受的响应,没有办法让两者显示在同一类型中,是吗? (2认同)

Bri*_*ian 6

就像 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)

因为它是一个类而不是一个模块,所以你失去了“打开我的”的能力(但获得了重载的能力);因此,这可能是也可能不是您可以接受的替代方案,具体取决于您在做什么。


ole*_*egz 6

在我的一个项目中,目标是放置文件操作CpRm分离模块,但不需要用户为这两个任务打开两个命名空间。

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)