使用独立开关编译并从另一个项目引用时,F#函数更改类型

时间:2015-01-22 21:23:24

标签: f#

在F#库的Visual Studio项目中,我将函数定义为

let inline Estimate (s : ^a seq) (f : float) (w : int) : float * float = ..

Estimate的类型是

val Estimate : s:seq<'a> -> f:float -> w:int -> float*float

从该项目中的脚本调用Estimate按预期工作。

现在,如果我使用--standalone开关编译项目并引用另一个项目的输出DLL,Estimate将显示为

Estimate<'a,'a>(s: Collections.Generic.IEnumerabls<'a>, f: float, w:int) : float*float

即。它有一些原因现在需要元组参数。 因此以下不起作用

let q, p = EstimationQuality.Estimate x f 1 // This value is not a function and cannot be applied

但用元组参数调用它可以正常工作

let q, p = EstimationQuality.Estimate (x, f, 1) // No problem.

这里有什么问题?这是编译器中的错误吗?

修改
深入挖掘,问题似乎与使用LanguagePrimitives.GenericZero

有关

虽然问题实际上是使用tuple参数调用编译的,但在调用Estimate时会出现运行时错误。

  

“System.TypeInitializationException”类型的未处理异常   发生在LibraryTest.dll

中      

附加信息:类型初始化程序   'GenericZeroDynamicImplTable`1'引发了异常。

1 个答案:

答案 0 :(得分:2)

编译一个用于F#的F#DLL,使用独立开关不是一个好主意。

为什么呢?因为所有F#元数据都丢失了,因为整个F#类型都包含在DLL中,因此这些类型与调用DLL或fsi的F#应用程序的类型具有不同的标识。

调用者程序集使用Fsharp.Core.dll中的类型,这些类型现在与独立编译的DLL中使用的类型不同。

这就是为什么你会看到tupled参数,从C#中可以看出它根本不理解F#元数据。

使用静态约束的通用内联函数也会中断,因为它们需要在调用站点内联元数据。

将调用者程序集编译为独立会使事情变得更糟,然后您将拥有3组具有不同身份的Fsharp类型。

我认为独立开关在“最终用户”应用程序中使用时很好。