【问题标题】:F#, namespaces, modules, fs and fsxF#、命名空间、模块、fs 和 fsx
【发布时间】:2011-01-22 05:40:26
【问题描述】:

我知道otherquestions 关于 F# 中的模块和命名空间,但它们现在对我没有帮助。

我有一个项目

Utilities.fs

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

Functions.fs

namespace Company.Project.Namespace
open Utilities

module Functions = 
     //stuff here

我正在尝试在 fsx 中测试它们:

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

当我尝试使用 Alt-Enter 将其发送到 FSI 时,这给了我 error FS0039: The namespace or module 'Utilities' is not defined。

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

奇怪的是后台编译器并没有对我大喊大叫。

这似乎可行,但它是正确的方法吗?

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

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

【问题讨论】:

    标签: f# namespaces module projects-and-solutions f#-interactive


    【解决方案1】:

    我不是 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()
    

    如果我#load不止一次我得到例如

    > [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
    

    请注意,FSI_0003.Foo.Bar 似乎掩盖了 FSI_0002 版本。

    所以我在想 F# 规范中所说的部分

    在命名空间声明组中, 命名空间本身是隐式的 如果前面有任何命名空间,则打开 声明组或引用 大会对此做出了贡献 命名空间,例如

    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
    

    但是这只会打开命名空间 由前面的命名空间构成 声明组。

    不与 FSI 交互,因为 FSI 对命名空间的了解有限。具体来说,我希望您的示例中的“第二个#load”会打开,例如FSI_000N+1 的命名空间版本,而之前的代码在 FSI_000N 中。这也许可以解释为什么显式的open 交互可以修复它;在稍后尝试(隐式)引用它之前,您将现有的、未隐藏的 FSI_000N 内容提升到顶层。

    【讨论】:

    • 是的,碰巧,我的问题是我实际代码的一个淡化示例。我最终通过重新打开每个 #load... 之间的命名空间来使其工作...
    【解决方案2】:

    我对此也比较陌生,但是当我在 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
    

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

    【讨论】:

      猜你喜欢
      • 2010-11-12
      • 2011-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-01
      • 1970-01-01
      • 2014-01-26
      • 2016-05-20
      相关资源
      最近更新 更多