F#:为什么可以';当B是a的子类型时,将B类型的对象约束为a类型的列表?

F#:为什么可以';当B是a的子类型时,将B类型的对象约束为a类型的列表?,f#,F#,根据本网站的第三个示例,F#列表可以包含不同类型的对象,只要这两种类型都来自同一个超级类型。但是,我无法让cons(::)操作符将子类型添加到超类型列表中 module test type A() = member this.x = 2 type B() = inherit A() member this.y = 4 let mutable myList : A list = [] myList <- [B()] // Valid myList <- B

根据本网站的第三个示例,F#列表可以包含不同类型的对象,只要这两种类型都来自同一个超级类型。但是,我无法让cons(::)操作符将子类型添加到超类型列表中

module test

type A() =
    member this.x = 2

type B() =
    inherit A()
    member this.y = 4

let mutable myList : A list = []
myList <- [B()] // Valid
myList <- B()::myList // Invalid: This expression was expected to have type A but here has type B
模块测试
A型()=
成员:x=2
B类()=
继承
成员:y=4
让可变myList:A list=[]
myListF#并不总是自动插入向上转换(转换为基本类型),因此您必须插入一个显式转换,将
B
值转换为
a
类型的值

请注意,F#区分了向基类的向上转换(总是正确的)和向派生类的向下转换(可能失败的)

您可以使用
upcast
关键字,也可以使用
expr:>类型
符号。在这两种情况下,编译器都可以填写所需的目标类型,因此您只需编写:

myList <- (upcast B())::myList
myList <- (B() :> _)::myList

myList Try
let mutable myList:#列表=[]
myList@ildjarn您的第一个建议会导致一个警告:此构造导致代码没有其类型注释所指示的那么通用。在或附近使用“#”、“"”或其他类型批注所隐含的类型变量已被约束为类型“B”。你的第二个建议似乎有效。