[英]Why is F# generic type inference different on constructors?
這種情況(簡化到沒有多大意義)由F#的類型系統正確處理:
type HumanBeing() = class end
type Animal() = class end
type CreatureController() =
member this.Register creature = creature
type CreatureFactory() =
let anAnimal = new Animal()
let aHuman = new HumanBeing()
member this.GiveMeAnAnimal =
(new CreatureController()).Register anAnimal
member this.GiveMeAHuman =
(new CreatureController()).Register aHuman
正確推斷出CreatureController.Register的類型:'a - >'a,因此可以使用兩個不同的參數調用它。
現在,以下版本略有不同:它不是將creature作為參數傳遞給CreatureController.Register,而是傳遞給它的構造函數。
type HumanBeing() = class end
type Animal() = class end
type CreatureController(creature) =
member this.Register = creature
type CreatureFactory() =
let anAnimal = new Animal()
let aHuman = new HumanBeing()
member this.GiveMeAnAnimal =
(new CreatureController(anAnimal)).Register
member this.GiveMeAHuman =
(new CreatureController(aHuman)).Register
第二個例子沒有編譯,因為Register被推斷為Animal,所以你不能調用new CreatureController(aHuman)
。
(注意:在這個簡化的情況下,Factory顯然有缺陷,因為它總是返回相同的animal / humanBeing,但是如果用函數替換anAnimal / aHuman,這種行為不會改變。)
為什么在第二種情況下CreatureControlled不是通用的? 這是編譯器限制嗎? 我錯過了一些非常基本的東西(還在學習......)?
在第一種情況下,正如您所說, Register
被推斷為通用的,因此它有效。 在第二種情況下,您將兩種不同的類型傳遞給非泛型類的構造函數。 在這種情況下必須推斷出具體類型。 如果你將類型args添加到生物控制器,它可以工作:
type HumanBeing() = class end
type Animal() = class end
type CreatureController<'T>(creature:'T) =
member this.Register = creature
type CreatureFactory() =
let anAnimal = new Animal()
let aHuman = new HumanBeing()
member this.GiveMeAnAnimal =
(new CreatureController<_>(anAnimal)).Register
member this.GiveMeAHuman =
(new CreatureController<_>(aHuman)).Register
區別在於類型參數必須在類型上是顯式的,而不是在函數上。 此外,構造函數只能處理類型本身聲明的類型參數。
在構造函數的情況下,你可能(或至少是模棱兩可的)你認為類型本身是通用的,例如
type CreatureController<'T>(creature:'T) = ...
在F#中,必須始終明確指定類型定義的泛型參數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.