定义模块VS.NET与F#Interactive

时间:2012-08-28 09:07:31

标签: f# f#-interactive

我编写了这段代码,它在VS.NET 2010中编译并完美运行

module ConfigHandler
open System
open System.Xml
open System.Configuration

let GetConnectionString (key : string) =
  ConfigurationManager.ConnectionStrings.Item(key).ConnectionString

然而,当我执行控制+ A和Alt + Enter将此发送给FSI时,我收到错误

ConfigHandler.fs(2,1):错误FS0010:定义中结构化构造的意外启动。预期'='或其他令牌。

行。

所以我将代码更改为

module ConfigHandler =
  open System
  open System.Xml
  open System.Configuration

  let GetConnectionString (key : string) =
    ConfigurationManager.ConnectionStrings.Item(key).ConnectionString

现在控制+ A,Alt + Enter成功,我很好地告诉我

模块ConfigHandler =开始   val GetConnectionString:string - >串 端

但是现在如果我尝试在VS.NET 2010中编译我的代码,我会收到一条错误消息

库或多文件应用程序中的文件必须以命名空间或模块声明开头,例如'namespace SomeNamespace.SubNamespace'或'module SomeNamespace.SomeModule'

我怎么能同时拥有这两个?能否在VS.NET中编译并能够将模块发送到FSI?

2 个答案:

答案 0 :(得分:16)

在你的两个代码片段之间存在一个微小但至关重要的区别,这应该归咎于此。

F#有两种方式来声明module。第一个是"顶级模块",声明如下:

module MyModule
// ... code goes here

声明模块的另一种方式是"本地模块",如下所示:

module MyModule =
    // ... code goes here

"顶级"之间的主要区别和#34;本地"声明是本地声明后跟一个=符号和#34; local"中的代码。模块必须缩进。

您收到第一个代码段的ConfigHandler.fs(2,1): error FS0010: Unexpected start of structured construct in definition. Expected '=' or other token.消息的原因是您无法在fsi中声明顶级模块。

当您将=符号添加到模块定义时,它会从顶级模块更改为本地模块。从那里,您得到错误Files in libraries or multiple-file applications must begin with a namespace or module declaration, e.g. 'namespace SomeNamespace.SubNamespace' or 'module SomeNamespace.SomeModule',因为本地模块必须嵌套在顶级模块或命名空间中。 fsi不允许您定义命名空间(或顶级模块),因此如果您想将整个文件复制粘贴到fsi,那么它的唯一工作方式就是如果您使用编译指令作为@pad提到。否则,您只需将本地模块定义(不包含命名空间)复制粘贴到fsi中,它们应该按预期工作。

参考: Modules (F#) on MSDN

答案 1 :(得分:7)

常见的解决方案是保留第一个示例并创建一个引用该模块的fsx文件:

#load "ConfigHandler.fs"

您可以加载多个模块并编写用于实验的管道代码。

如果您确实要将ConfigHandler.fs直接加载到F#Interactive,可以使用INTERACTIVE符号和compiler directives

#if INTERACTIVE
#else
module ConfigHandler
#endif

适用于fsi和fsc。