使用F#,当我必须明确地强迫为了获得模式匹配表达式来键入正确的检查值,其类型的父类问题摘要如何隐式转换为F#模式匹配中的常见超类型?
的时刻。我理想地喜欢一个更干净的方式。
例
假设我有一些类层次:
type Foo() =
abstract member Value : unit -> string
type A (i:int) =
inherit Foo()
override this.Value() = i.ToString()
type B (s:string) =
inherit Foo()
override this.Value() = s
理想的情况下,并在正常一些编程语言,我会写下面的等价:
let bar (i:int) : Foo =
match i with
| 1 -> B "one"
| _ -> A i
但是这不能正确地输入检查,给我错误,“这个表达式预计有Foo类型,但她e有B型“。我不明白为什么编译器没有足够的信息来推断匹配表达式的公共超类型,然后检查公共超类型是'Foo'。
目前我被迫在模式匹配任何情况下提供一个明确的威逼:
let bar2 (i:int) : Foo =
match i with
| 1 -> (B "one") :> Foo
| _ -> (A i) :> Foo
我想避免这种情况。
其它注意事项
- 直觉认为,这是一个比较普遍的问题的结果。我会想,虽然模式匹配这样的事情,或者如果语句也表现出相同的属性,会有一个类型检查规则来说明常见的超类型。
- 之前有人建议 - 我明白,如果A或B是对象表达式这将工作,但我真正的例子是创建C#类的实例,他们是正常的类。
- 有没有一种方法可以让我声明隐式转换类型的函数,例如scala已经有了,所以我可以将自动转换应用到我在做这一代的模块中?
感谢您对此事的任何帮助。
类型检查器没有对派生类型进行任何欺骗的原因是,首先它会使类型检查步骤更加复杂,其次它会允许您引入细微的错误。例如,请考虑以下内容: 与我匹配 | 1 - > B(“one”) | 2 - >“stuff” 好吧,System.String和B共享公共基类型System.Object,所以匹配表达式的结果是obj类型。这是99.9%不是你想要的。 – 2010-10-11 20:00:45
的确如此,尽管在OP所询问的具体实例中,他已经将函数返回类型声明为“:Foo”,所以我认为推理者也许并不完全不合理地将其用作最大值较低的值,绑定什么的。尽管如此,我还没有考虑过所有的影响。 – Brian 2010-10-11 20:04:32
我认为'x:> _'比'upcast x'读得更好,但也许这就是我。不过,这场比赛的分支并不一致。 – kvb 2010-10-11 22:08:15