2016-09-26 43 views
3

我已經遇到了這些錯誤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,所以我沒有看到如何使用該知識(刪除類型裝飾)來幫助我。

+1

您可以通過不使用'function'並使用顯式參數+'match'來解決此問題。函數產生一個值;值不能內聯。靜態成員inline getType x =匹配x與Int _ - > MyType.Integer | Float _ - > MyType.Float' – ildjarn

+1

@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

+1

@ildjarn,順便說一句,我更新了Q.(實施你的建議),以避免錯誤從何而來。沒有編譯,F#編輯器,推理和智能感知,不要抱怨。 – Abel

回答

2

似乎是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 
+2

這是正確的,它解決了這個問題,但代碼順序不是_incorrect_:在一個類中,在具有'和'的類之間,順序是不相關的。我昨天[報道這是一個F#的bug](https://github.com/Microsoft/visualfsharp/issues/1565),我們似乎得出了大致相同的結論:)。 – Abel

+0

這是正確的。感謝您報告錯誤。我最好的猜測是,甚至在解析模塊代碼時,F#編譯器也試圖在不知道它的實現的情況下內聯函數,這當然會失敗。 – CodeMonkey