Types 为什么F#泛型类型推断在构造函数上不同?

Types 为什么F#泛型类型推断在构造函数上不同?,types,f#,Types,F#,这种情况(简化到没有多大意义的程度)由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 HumanBein

这种情况(简化到没有多大意义的程度)由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,因此可以使用两个不同的参数调用它

现在,下面的版本有一点不同:它不是作为参数传递给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
第二个示例没有编译,因为寄存器被推断为动物,所以您不能调用
新的CreatureController(aHuman)

(注意:在这种简化的情况下,工厂显然存在缺陷,因为它总是返回相同的动物/人,但如果用函数替换动物/人,这种行为不会改变。)


为什么CreatureControl在第二种情况下不被创建为泛型?这是编译器限制吗?我是否遗漏了一些非常基本的东西(仍在学习…?

在第一种情况下,如您所述,
寄存器被推断为泛型,因此它是有效的。在第二种情况下,将两种不同的类型传递给非泛型类的构造函数。在这种情况下,必须推断出具体类型。如果您将类型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 HumanBeing()=类结束
类型Animal()=类结束

类型CreatureController在构造函数的情况下,很可能(或至少是不明确的)是指类型本身是泛型的,例如

type CreatureController<'T>(creature:'T) = ...

类型CreatureControllerI我认为总结是-你不能有一个本身是泛型的构造函数(但泛型方法是完全可以的)。泛型构造函数意味着整个类型都是泛型的,必须显式声明。从答案中可以明显看出,类型推断有时会有点令人头痛,我仍然更喜欢使用类型注释来让事情更清楚。在您的例子中,如果您在控制器构造函数上放置了类型注释,那么可以帮助您找到problem@Tomas你的句子总结得很好。@Ankur我发现大多数时候它都很有效(tm),我发现自己很少被类型“分散”注意力。我认为如果你从不使用类型推断,你就会错过一个很好的功能。@Francesco De Vittori:我确实使用类型推断,但大多数情况下,当推断的类型在附近时,例如:
let a=10
,而不是类型推断基于以后的使用,因为这会使读取代码变得不那么容易(没有IDE,情况会更糟)。