在类型成员中使用内联失败并显示 FS1114、FS1113、FS1116、FS1118

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,我不知道如何使用这些知识(删除类型修饰)来帮助我。

Cod*_*key 3

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)

  • 你是对的,这解决了问题,但代码顺序不是_不正确_:在类内部以及带有“and”的类之间,顺序是无关紧要的。我昨天[将此作为错误报告给 F#](https://github.com/Microsoft/visualfsharp/issues/1565),我们似乎得出了大致相同的结论:)。 (2认同)