1

这非常奇怪,我希望有人会有一些见解来理解这一点。

我有一个 F# 2.0(Visual Studio 2010,针对 .Net 4.0)解决方案,它在我最初创建它的位置可以正常工作,但是如果我尝试将它复制到一个新文件夹(因为我想将它签入源代码管理),我在构建时遇到了一些非常奇怪的错误。它们往往是这样的:

error FS0803: Invalid use of a type name and/or object constructor. If necessary use 'new' and apply the constructor to its arguments, e.g. 'new Type(args)'. Overloads are:  None() : unit.

或者

error FS0001: This expression was expected to have type     obj option     but here has type     Some<'a>

这些错误在使用选项类型时发生,其中一种用法的简单示例是:

let asOption e = 
    match e with
    | null -> None
    | _ -> Some(e)

现在,请记住,这是一个在其原始位置编译得很好的解决方案。我已经尝试过类似 Clean/Rebuild、删除 obj 和 bin 目录、重新启动 Visual Studion 等显而易见的方法,但还是一样。

在这两种情况下,引用 DLL 都是相同的,GAC 的 DLL 是从 GAC 引用的,非 GAC 的 dll 是从相同的相对路径复制和引用的。只是为了好玩,我什至比较了用于编译每个解决方案的 Fsc.exe 调用的输出窗口文本,以确保在两种情况下都使用相同的参数调用编译器,当然,确实如此。

任何人都知道可能导致这种情况的原因吗?我是否以某种方式从 GAC 中获得了一些奇怪的 FSharp.Core.dll 版本?我只是倒霉蛋中最倒霉的一个吗?

4

3 回答 3

2

所以奇怪的症状有一个同样奇怪的原因。

事实证明,我引用的其中一个 DLL(每个项目都有的无处不在的“核心”垃圾抽屉 dll)必须有一些扩展方法,这些方法会导致编译器和 Visual Studio 使用的类型推断出现一些问题。

当我删除open MyProject.Core并用完全限定名称替换对我正在使用的类型的任何引用时,奇怪的错误神奇地消失了。

所以,在这一点上,还有两个问题:

  1. 那里有什么样的疯狂扩展方法可能导致这种情况
  2. 为什么原始解决方案/项目不受此影响?(我猜这可能与将引用传递给 Fsc.exe 调用的顺序有关……但我不确定)。

我实际上可能会深入挖掘以尝试找出#1的答案。我不确定它是否暴露了 F# 编译器的某种错误(可疑),或者我的同事是否只是在使用扩展方法做一些不自然的事情(很可能)

更新:看起来有人有些嫉妒 F# 并Option<T>在 Core 项目中创建了一个类。几乎解释了一些事情。我没有尝试查看 Fsc.exe 调用中包含的顺序是否有所不同,但我有一种感觉。

于 2012-06-26T14:47:36.167 回答
0

假设 F# 编译器是确定性的,那么显然在调用它的方式上肯定存在一些差异,可能在环境变量中。您是否尝试过从命令行运行 MSBuild?它通常对这类事情有所帮助。

一种猜测是 F# 为您的代码推断出不同的类型。您是否尝试过将其限制为只需要处理简单类型?例如:

let asOption (e: obj) =
    match e with
    | null -> None
    | _ -> Some(e)

要不然:

let asOption<'T> (x: 'T) : option<'T> =
    if x :> obj = null then None else Some x

后者摆脱了对泛型参数的空约束。

于 2012-06-26T14:20:52.850 回答
0

参考文献几乎不应该来自 GAC,它们应该来自Reference Assemblies. 发布您正在见证的 fsc.exe 命令行,也许它会更清楚。我猜 FSharp.Core 参考以某种方式搞砸了(可能与它的参考程序集旁边的 sigdata/optdata 文件有关?)

(不过,一个非常奇怪的症状的点!)

于 2012-06-26T04:23:44.333 回答