我已经遇到了这些错误before in a much more complex scenario。从那以后,我简化了很多东西,并且有很长时间的工作代码,直到我需要覆盖Equals
。它使用了F#似乎不喜欢的内联成员。使用内联类型成员失败,FS1114,FS1113,FS1116,FS1118
基本上,该方案可归纳为以下代码:
[<Flags>]
type MyType =
| Integer = 0b0001
| Float = 0b0010
module Test =
[<CustomEquality;NoComparison>]
type SomeType =
| Int of int64
| Float of float
override x.Equals other =
match other with
| :? SomeType as y ->
// following line throws on compiling this
match SomeType.getType x &&& SomeType.getType y with
| MyType.Integer -> int64 x = int64 y // highest type is integer (both are int)
| MyType.Float -> float x = float y // highest type is float (either is or both are float)
| _ -> false // impossible
| _ -> false
override x.GetHashCode() =
match x with Int i -> hash i | Float f -> hash f
static member inline op_Explicit(n: SomeType): float =
match n with
| Int i -> float i
| Float f -> f
static member inline op_Explicit(n: SomeType): int64 =
match n with
| Int i -> i
| Float f -> int64 f
static member inline getType x =
match x with
| Int _ -> MyType.Integer
| Float _ -> MyType.Float
以下错误提出了(这有点像我刚才的问题而是涉及复杂的鸭子类型)。
错误FS1114:值“Test.SomeType.getType”被内嵌标记,但在优化环境没有义务
错误FS1113:值“的getType”被内嵌标记,但其实现使用内部的或私人功能不足
警告FS1116:标记为'inline'的值具有意外值
错误FS1118:未内联标记为'inline'的值'getType',可能是因为递归值标记为' inline'
现在,没有递归值,并且目标类型是已知的(由于在匹配模式中隐式转换为SomeType
),所以我认为没有理由使这种内联是不可能的。
有没有人有这方面的想法?或者一个模式,包括内联op_Explicit
(如果您删除getType
,您将会得到这些错误),最好是getType
内联?我知道我可以通过一个面向对象的层次结构来解决这个问题,但是我宁愿使用这种方法,为了清晰起见(类型系统是一个晶格,而不是层次结构)和性能(更早带有内联的版本显示测试场景速度提高了4倍以上,并且速度很重要)。
在事后,下面,简单的场景也会引发这些错误:
module Test =
type SomeType =
| Int of int64
| Float of float
static member MyEquals (x, other: SomeType) =
// following line throws on compiling this
float x = float other
static member inline op_Explicit(n: SomeType): float =
match n with
| Int i -> float i
| Float f -> f
static member inline op_Explicit(n: SomeType): int64 =
match n with
| Int i -> i
| Float f -> int64 f
当我删除类型装饰other: SomeType
,错误消失。我不知道为什么这很重要,因为具有相同静态推断方法的较窄类型不应引起这个错误,我想。
而且由于override x.Equals
的类型注释为obj
,所以我没有看到如何使用该知识(删除类型装饰)来帮助我。
您可以通过不使用'function'并使用显式参数+'match'来解决此问题。函数产生一个值;值不能内联。静态成员inline getType x =匹配x与Int _ - > MyType.Integer | Float _ - > MyType.Float' – ildjarn
@ildjarn,感谢您的建议,但这并不会改变错误,尝试它,并将其复制到FSI中。但是你是对的,有时'inline'与'function'(静态成员)一起工作,有时不能(绑定),不知道为什么,[有一个功能请求允许内联'let f = fun x - > ... '](HTTPS://fslang.uservoice。com/forums/245727-f-language/suggestions/6237585-allow-inline-keyword-in-the-case-let -f-fun-a),但那是另一回事。无论哪种方式,错误依然存在。 – Abel
@ildjarn,顺便说一句,我更新了Q.(实施你的建议),以避免错误从何而来。没有编译,F#编辑器,推理和智能感知,不要抱怨。 – Abel