Sharing types across F# .fsx files

前端 未结 3 1291
感情败类
感情败类 2021-01-11 11:53

Is there a way to share types across fsx files?

When using #load to load the same file containing a type from multiple FSX files they seem to be prefixed into a diff

相关标签:
3条回答
  • 2021-01-11 12:00

    As for

    http://msdn.microsoft.com/en-us/library/dd233169.aspx

    [.fsx files are] used to include informal testing code in F# without adding the test code to your application, and without creating a separate project for it. By default, script files are not included in the build of a project even when they are part of a project.

    This means that if you have a project with enough structure to be having such dependency problems, you should not use .fsx files, instead write modules/namespaces using .fs files. That is, you really should compile them types into an assembly.

    The f# interactive interpreter generates assembly for each loaded files. If you load a file twice, the bytecode is generated twice, and the types are different even if they have the same definition and the same name. This means that there is no way for you to share types between two .fsx files, unless one of them includes the other.

    When you #load a file which has the same types as ones already present in your environment, the f# interactive interpreter can use two different strategy:

    1. refuse to load the file if conflicts with existing names arises (complaining that some stuff is already defined)
    2. put the names in FS_00xx namespace (so that they are actually different types from the ones you already loaded), eventually opening the resulting namespace so that names are available from interactive session.

    Since fsx files are supposed to be used as informal test it is more user-friendly to use the second approach (there are also technical reason for which the second approach is used, mainly dependent on .net VM type system, and the fact that existing types cannot be changed at runtime).

    0 讨论(0)
  • 2021-01-11 12:15

    [Note: This is a more specific answer to a more specific question that is a duplicate of this one.]

    I don't think there is a nice and easy solution for this. The one solution I have been using in some projects (like the F# snippets web site) is to have only one top-level fsx file that loads a number of fs files. For example, see app.fsx.

    So, you would have common.fs, intMapper.fs and stringMapper.fs that would be loaded from caller.fsx as follows:

    #load "common.fs"
    #load "stringMapper.fs"
    #load "intMapper.fs"
    open Common
    

    Inside stringMapper.fs and intMapper.fs, you do not load common.fs. The common types will be loaded by caller.fsx before, so things will work.

    The only issue with this is that intMapper.fs now isn't a standalone script file - and if you want to get autocomplete in an editor, you need to add a fsproj file that specifies the file order. In F# snippets project, there is a project file which specifies the order in whch the editor should see and load the files.

    0 讨论(0)
  • 2021-01-11 12:19

    Have all the #load and #open directives in the file you actually run from fsi.exe (C in the example below), and make sure the loaded files themselves do not #load their own dependencies:

    Files A.fsx, B.fsx, C.fsx. B depends on A. C depends on B and A.

    B contains

    //adding the code below would cause the types defined in A to be loaded twice
    //#load "A.fsx"
    //#open A
    

    C contains

    #load "A.fsx"
    #open A
    #load "B.fsx"
    #open B
    

    Unfortunately this then makes all the files hard to edit from Visual Studio - the editor doesn't know about their dependencies and shows all sorts of errors.

    Therefore this is a bit of a hack, and the recommended way seems to be to have a single .fsx file and compile everything else into a .dll :

    // file1.fsx
    #r "MyAssembly.dll"
    

    https://msdn.microsoft.com/en-us/library/dd233175.aspx

    0 讨论(0)
提交回复
热议问题