Abe*_*bel 5 f# type-inference inline
我之前在更复杂的场景中也遇到过这些错误。从那时起,我简化了很多事情,并在很长一段时间内拥有工作代码,直到我需要重写Equals. 它使用 F# 似乎不太满意的内联成员。
基本上,该场景可以用以下代码来概括:
[<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
Run Code Online (Sandbox Code Playgroud)
出现以下错误(这与我之前的问题类似,但涉及复杂的鸭子类型)。
错误 FS1114:值“Test.SomeType.getType”被标记为内联,但未在优化环境中绑定
错误 FS1113:值“getType”被标记为内联,但其实现使用了无法充分访问的内部或私有函数
警告 FS1116:标记为“内联”的值具有意外值
错误 FS1118:无法内联标记为“内联”的值“getType”,可能是因为递归值被标记为“内联”
现在,没有递归值,并且目标类型已知(作为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
Run Code Online (Sandbox Code Playgroud)
当我删除类型修饰时other: SomeType,错误消失。我不知道为什么这很重要,因为我认为具有相同静态推断方法的较窄类型不应该引发此错误。
由于override x.Equals具有 的类型注释obj,我不知道如何使用这些知识(删除类型修饰)来帮助我。
F# 编译器似乎无法对无序代码进行内联。正如您在下面的评论中正确指出的那样,这似乎是一个错误。
open System
[<Flags>]
type MyType =
| Integer = 0b0001
| Float = 0b0010
module Test =
[<CustomEquality;NoComparison>]
type SomeType =
| Int of int64
| Float of float
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
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
Run Code Online (Sandbox Code Playgroud)