Split F# modules across multiple files

前端 未结 5 1787
攒了一身酷
攒了一身酷 2021-01-01 08:51

Is it possible to split an F# module across files?

According to the book I have it is, but the book is probably outdated (Foundations of F#)

相关标签:
5条回答
  • 2021-01-01 09:30

    I sometimes split a type over several places, like this:

    module Foo
    
    type Partial = Bar | BarInt of int
    
    module Bar
    
    type Foo.Partial with
        member x.Extend = 5
    
    
    let b = Foo.Bar.Extend
    

    where modules Foo and Bar are in different files.

    0 讨论(0)
  • 2021-01-01 09:37

    Apparently not:

    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.
    

    Update: the error has changed in F# 4.0, it is now:

    error FS0248: Two modules named 'Module' occur in two parts of this assembly

    where Module is the fully qualified name of your assembly, including the namespace part.

    0 讨论(0)
  • 2021-01-01 09:38

    Like Kurt says, you can add extension methods to types, and thus

    // File1.fs
    namespace Foo
    
    type Mine() =
        static member f1 () = ()
    

    then

    // File2.fs
    type Foo.Mine with
        static member f2() = ()
    
    Foo.Mine.    // both f1 and f2 here
    

    Since it's a class and not a module, you lose the ability to do 'open Mine' (but gain the ability to overload); thus this may or may not be an acceptable alternative for you depending on exactly what you're doing.

    0 讨论(0)
  • 2021-01-01 09:40

    The type extensions are cool, and hopefully they will allow to be cross file, while still being intrinsic. If you do a type extension in the same file, it compiles to one class, and the extension has access to private members and so on. If you do it in another file, it's just an "optional" extension, like C# static extension methods. (Even though the F# specs say differently.)

    I'd be surprised if this isn't addressed at some point, if only for designer support. If intrinsic type extensions could be anywhere in the assembly, that'd be pretty slick.

    Another option, which might not be what you want, is to create a type and a module, call the module the same name, and then add the ModuleSuffix flag to it:

    type Foo() = 
        static member Bar = 1
    
    [<CompilationRepresentationAttribute(CompilationRepresentationFlags.ModuleSuffix)>]
    module Foo =
        let Baz = 2
    
    printfn "%d %d" Foo.Bar Foo.Baz
    

    This is used in the F# libraries, so they can have a type List or whatever, along with tons of helper stuff in a module.

    0 讨论(0)
  • 2021-01-01 09:42

    On one of my projects the goal was to place file operations Cp and Rm to separate modules, but do not require user to open two namespaces for both tasks.

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

    Here're my modules:

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

    and the other one:

    namespace Xake.FileTasks
    
    [<AutoOpen>]
    module CpImpl =
        let Cp filemask target =
    ...
    
    0 讨论(0)
提交回复
热议问题