Dot-Net

F# 和鴨式打字

  • May 20, 2015

假設我在 F# 中定義了以下兩種類型:

type Dog = { DogName:string; Age:int }
type Cat = { CatName:string; Age:int }

我期待以下方法適用於貓和狗:

let isOld x = x.Age >= 65

實際上,似乎發生的事情是isOld只接受貓:

let dog = { DogName = "Jackie"; Age = 4 }
let cat = { CatName = "Micky"; Age = 80 }

let isDogOld = isOld dog //error

我希望 F# 足夠聰明,可以X為貓和狗定義某種“虛擬”介面,以便isOld接受 X 作為參數,而不是Cat.

這不是 F# 在任何情況下都可以處理的事情,對嗎?似乎 F# 類型推斷系統不會做比 C# 對var類型變數所做的更多的事情。

您可以定義一個inline帶有成員約束的函式,或者走經典路線並使用一個介面(在這種情況下可能是首選)。

let inline isOld (x:^T) = (^T : (member Age : int) x) >= 65

編輯

我只記得這不適用於記錄類型。從技術上講,它們的成員是欄位,儘管您可以使用with member .... 無論如何,您都必須這樣做才能滿足介面。

作為參考,以下是實現具有記錄類型的介面的方法:

type IAging =
 abstract Age : int

type Dog = 
 { DogName : string
   Age : int } 
 interface IAging with
   member this.Age = //could also be `this.Age = this.Age`
     let { DogName = _; Age = age } = this
     age

引用自:https://stackoverflow.com/questions/7065939