2017-10-04 71 views
1

我想要创建一个Person实例。人是一种动物。当我尝试创建一个Person时,IDE对我说:“这个表达式预计会有'Person'类型,但是这里有'Animal'类型。使用同名联盟类型创建新对象

type Person(name) = 
    member this.Name: string = name 

type Animal = 
| Person of Person 
| Cat 
| Dog 

let person: Person = Person(name = "John") 
+0

我不知道为什么它是这样的,所以我不会将它作为答案添加它,但是如果您添加'new',它将起作用:'let person:Person = new Person(name =“John”)''。 – MarcinJuraszek

+0

@MarcinJuraszek我不想使用'new'关键字,如果我使用'new',IDE说我'新'是多余的。 –

+0

有趣。我只在F#Interactive中测试过它。 – MarcinJuraszek

回答

1

问题是Person引用了歧视联盟的类型和大小写。

可以反转的定义,因此将解决最后一个:

type Animal = 
    | Person of Person 
    | Cat 
    | Dog 
and 
    Person (name) = 
     member this.Name: string = name 

let person: Person = Person(name = "John") 

// then to create an animal 
let animal = Animal.Person (Person(name = "John")) 

替代解决方案是使用new关键词作为@MarcinJuraszek建议的意见或考虑杜情况和不同的名称类型。

+0

“类型,例外或模块'Person'的重复定义”。 –

+0

在这种情况下,你会如何创建一个'Animal'类型的人? – Matiasd

+0

@Matiasd我只发布IDE所说的错误。联合人员没有参数,但Person类是。 –

1

在F#中,名称可以作为类型和值的绑定,并且您可以随时重新定义名称“指向”的名称。例如。

// lets define type A 
type A(name) = member this.Name : string = name 
let x = A("test") 

// lets "bind" the type name 'A' to a new type 
type A(number) = member this.Number : int = number 
let y = A(10) 

printfn "type name of x: %s" (x.GetType().Name) // prints 'type name of x: A' 
printfn "type name of y: %s" (y.GetType().Name) // prints 'type name of y: A' 

所以xy都是一个名为A型的,但不一样的。同样的逻辑适用于PersonAnimal.Person,并且取决于您定义它们的顺序,最后定义的将是在键入Person时引用的那个。

如上所述,您可以使用新的或定义顺序来访问两者。您也可以决定将Person类放在与Animal不同的模块中。

module Inner = 
    type Person(name) ... 

这样,您可以通过预先输入模块名称来访问您的类型。