【发布时间】:2012-03-27 15:56:15
【问题描述】:
考虑一下:
module Module1 =
type A() = class end
type B() = inherit A()
type C() = inherit A()
let f x = if x > 0 then new B() else new C()
最后一行产生了关于预期类型 B 的错误,但找到了类型 C。 好的,我可以假装理解:编译器不知道要推断哪个公共基础,以防万一。
但是你猜怎么着?即使我指定了函数类型,它仍然不起作用:
let f x : A = if x > 0 then new B() else new C()
现在这给了我两个错误:“A 预期,B 找到”和“A 预期,C 找到”。 怎么回事?为什么它看不到 B 和 C 都可以隐式转换为 A?
是的,我知道我可以使用upcast,就像这样:
let f x : A = if x > 0 then upcast new B() else upcast new C()
但是猜猜(再次)是什么? upcast 仅在存在显式函数类型声明的情况下有效!
换句话说,这是:
let f x = if x > 0 then upcast new B() else upcast new C()
还是报错。
WTF?!我真的必须在我的程序中添加 50% 的噪音来帮助编译器吗? 为何大肆宣传 F# 代码干净无噪音?
不知何故,这似乎不是真的。 所以问题是:我错过了什么吗?如何使这既紧凑又有效?
【问题讨论】:
-
子类型和类型推断不能很好地相处。
-
@OnorioCatenacci - 我不代表 Don 或团队发言。但是,我不确定是否建议在出现有关设计决策的问题时向 fsbugs 发送电子邮件 - 我认为这确实是用于错误报告和功能建议。
-
F# 确实试图通过提供object expressions 等替代方案来缓解(或引导您远离)此类情况。
-
@OnorioCatenacci:我并不是真的要建议改变设计。我最初的假设是设计并没有真正的限制,并且有一些简单的方法可以实现我想要的。然而,我现在从答案中看到,这确实是一个公认的限制,并且它或多或少有一些合理的理由支持。这就是我想知道的。
-
@Daniel:也许我应该更清楚一点,但我在常规程序设计过程中并没有遇到这种情况。我在尝试与 .NET 的其余部分进行互操作时遇到了这个问题,我不得不根据某些条件返回不同的派生对象。
标签: visual-studio-2010 inheritance f# type-inference