f#,名称空间,模块,fs和fsx。

时间:2022-10-13 16:10:43

I'm aware of other questions about modules and namespaces in F#, but they're not helping me right now.

我知道f#中关于模块和名称空间的其他问题,但是他们现在没有帮助我。

I've got a project with

我有一个项目。

Utilities.fs

Utilities.fs

namespace Company.Project.Namespace
module Utilities = 
     //stuff here

Functions.fs

Functions.fs

namespace Company.Project.Namespace
open Utilities

module Functions = 
     //stuff here

And I'm trying to test them in an fsx:

我试着用fsx来测试

#load "Utilities.fs"
#load "Functions.fs"

which gives me error FS0039: The namespace or module 'Utilities' is not defined when I try to send it to FSI with Alt-Enter.

这给了我错误FS0039:当我尝试用Alt-Enter发送给FSI时,没有定义名称空间或模块的实用程序。

I've tried adding same namespace at the top of the script file, but it doesn't like that.

我尝试在脚本文件的顶部添加相同的名称空间,但它不喜欢这样。

What's weird is that the background compiler doesn't shout at me.

奇怪的是,后台编译器不会对我大喊大叫。

This seems to work, but is it the right approch?

这似乎行得通,但这是正确的方法吗?

#load "Utilities.fs"
open Company.Project.Namespace
#load "Functions.fs"

Is there a 'reference' FSharp project somewhere, which contains examples of how to integrate all this stuff: namespaces, modules, classes, script files, tests etc.?

是否有一个“参考”FSharp项目,其中包含了如何集成所有这些东西的示例:名称空间、模块、类、脚本文件、测试等等。

2 个解决方案

#1


9  

I'm not an expert with FSI, but some experimentation suggests that namespaces are only supported by #load declarations (not via typical interactions - sending a namespace declaration group to VFSI via Alt-Enter does not work), and that different interactions contribute different 'instances'. For example, with the code file

我不是FSI的专家,但是一些实验表明名称空间只支持#load声明(不是通过典型的交互——通过Alt-Enter向VFSI发送名称空间声明组不工作),并且不同的交互贡献了不同的“实例”。例如,使用代码文件。

namespace Foo

type Bar() =
    member this.Qux() = printfn "hi"

namespace Other

type Whatever() = class end

namespace Foo

module M =
    let bar = new Bar()
    bar.Qux()

if I #load it more than once I get e.g.

如果我不止一次加载它,我就会得到。

> [Loading C:\Program.fs]
hi

namespace FSI_0002.Foo
  type Bar =
    class
      new : unit -> Bar
      member Qux : unit -> unit
    end
namespace FSI_0002.Other
  type Whatever =
    class
      new : unit -> Whatever
    end
namespace FSI_0002.Foo
  val bar : Bar

> #load @"C:\Program.fs";;
> [Loading C:\Program.fs]
hi

namespace FSI_0003.Foo
  type Bar =
    class
      new : unit -> Bar
      member Qux : unit -> unit
    end
namespace FSI_0003.Other
  type Whatever =
    class
      new : unit -> Whatever
    end
namespace FSI_0003.Foo
  val bar : Bar

> new Foo.Bar();;
> val it : Foo.Bar = FSI_0003.Foo.Bar

Note that it seems the FSI_0003.Foo.Bar shadowed the FSI_0002 version.

注意,它似乎是FSI_0003.Foo。Bar跟踪FSI_0002版本。

So I'm thinking the part of the F# spec that says

我在想f#规范的一部分。

Within a namespace declaration group, the namespace itself is implicitly opened if any preceding namespace declaration groups or referenced assemblies contribute to this namespace, e.g.

在名称空间声明组中,如果前面的名称空间声明组或引用的程序集对该名称空间有贡献,则隐式地打开名称空间。

namespace MyCompany.MyLibrary 

   module Values1 = 
      let x = 1

namespace MyCompany.MyLibrary 

   // Implicit open of MyCompany.MyLibrary bringing Values1 into scope

   module Values2 = 
      let x = Values1.x

However this only opens the namespace as constituted by preceding namespace declaration groups.

但是,这只打开了前面的名称空间声明组所组成的名称空间。

Does not interact with FSI, given FSI's limited understanding of namespaces. Specifically, I expect that the 'second #load' from your example opens e.g. FSI_000N+1's version of the namespace, whereas the prior code was in FSI_000N. Which maybe-explains why the explicit open interaction fixes it; you bring the existing, unshadowed FSI_000N stuff up to the top level before trying to (implicitly) reference it later.

不与FSI交互,因为FSI对名称空间的理解有限。具体地说,我希望您的示例中的“第二个#load”打开,例如FSI_000N+1的名称空间版本,而先前的代码是在FSI_000N中。这也许可以解释为什么显式的开放交互可以修复它;在尝试(隐式地)引用它之前,您将现有的、未被跟踪的FSI_000N内容带到顶层。

#2


8  

I'm relatively new at this too, but this is what works for me when I'm testing in an fsx file:

我对此也比较陌生,但这就是我在fsx文件中测试时的效果:

#if INTERACTIVE
#r @"C:\Program Files\FSharpPowerPack-2.0.0.0\bin\FParsec.dll"
#r @"C:\Program Files\FSharpPowerPack-2.0.0.0\bin\FParsecCS.dll"
#endif

open FParsec.Primitives  
open FParsec.CharParsers

followed by my code that uses these libraries.

接下来是使用这些库的代码。

#1


9  

I'm not an expert with FSI, but some experimentation suggests that namespaces are only supported by #load declarations (not via typical interactions - sending a namespace declaration group to VFSI via Alt-Enter does not work), and that different interactions contribute different 'instances'. For example, with the code file

我不是FSI的专家,但是一些实验表明名称空间只支持#load声明(不是通过典型的交互——通过Alt-Enter向VFSI发送名称空间声明组不工作),并且不同的交互贡献了不同的“实例”。例如,使用代码文件。

namespace Foo

type Bar() =
    member this.Qux() = printfn "hi"

namespace Other

type Whatever() = class end

namespace Foo

module M =
    let bar = new Bar()
    bar.Qux()

if I #load it more than once I get e.g.

如果我不止一次加载它,我就会得到。

> [Loading C:\Program.fs]
hi

namespace FSI_0002.Foo
  type Bar =
    class
      new : unit -> Bar
      member Qux : unit -> unit
    end
namespace FSI_0002.Other
  type Whatever =
    class
      new : unit -> Whatever
    end
namespace FSI_0002.Foo
  val bar : Bar

> #load @"C:\Program.fs";;
> [Loading C:\Program.fs]
hi

namespace FSI_0003.Foo
  type Bar =
    class
      new : unit -> Bar
      member Qux : unit -> unit
    end
namespace FSI_0003.Other
  type Whatever =
    class
      new : unit -> Whatever
    end
namespace FSI_0003.Foo
  val bar : Bar

> new Foo.Bar();;
> val it : Foo.Bar = FSI_0003.Foo.Bar

Note that it seems the FSI_0003.Foo.Bar shadowed the FSI_0002 version.

注意,它似乎是FSI_0003.Foo。Bar跟踪FSI_0002版本。

So I'm thinking the part of the F# spec that says

我在想f#规范的一部分。

Within a namespace declaration group, the namespace itself is implicitly opened if any preceding namespace declaration groups or referenced assemblies contribute to this namespace, e.g.

在名称空间声明组中,如果前面的名称空间声明组或引用的程序集对该名称空间有贡献,则隐式地打开名称空间。

namespace MyCompany.MyLibrary 

   module Values1 = 
      let x = 1

namespace MyCompany.MyLibrary 

   // Implicit open of MyCompany.MyLibrary bringing Values1 into scope

   module Values2 = 
      let x = Values1.x

However this only opens the namespace as constituted by preceding namespace declaration groups.

但是,这只打开了前面的名称空间声明组所组成的名称空间。

Does not interact with FSI, given FSI's limited understanding of namespaces. Specifically, I expect that the 'second #load' from your example opens e.g. FSI_000N+1's version of the namespace, whereas the prior code was in FSI_000N. Which maybe-explains why the explicit open interaction fixes it; you bring the existing, unshadowed FSI_000N stuff up to the top level before trying to (implicitly) reference it later.

不与FSI交互,因为FSI对名称空间的理解有限。具体地说,我希望您的示例中的“第二个#load”打开,例如FSI_000N+1的名称空间版本,而先前的代码是在FSI_000N中。这也许可以解释为什么显式的开放交互可以修复它;在尝试(隐式地)引用它之前,您将现有的、未被跟踪的FSI_000N内容带到顶层。

#2


8  

I'm relatively new at this too, but this is what works for me when I'm testing in an fsx file:

我对此也比较陌生,但这就是我在fsx文件中测试时的效果:

#if INTERACTIVE
#r @"C:\Program Files\FSharpPowerPack-2.0.0.0\bin\FParsec.dll"
#r @"C:\Program Files\FSharpPowerPack-2.0.0.0\bin\FParsecCS.dll"
#endif

open FParsec.Primitives  
open FParsec.CharParsers

followed by my code that uses these libraries.

接下来是使用这些库的代码。