问题描述
问题摘要
在使用f#的那一刻,我必须显式地将一个值强制转换为其类型的父类型,以便获得与模式匹配的表达式以正确进行类型检查.理想情况下,我想要一种更整洁的方式.
At the moment when using f# I must explicitly coerce a value to the parent type of its type in order to get pattern matching expressions to type check correctly. I would ideally like a neater way of doing.
示例
假设我有一些班级等级:
Suppose I have some class hierachy:
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
理想情况下,在某些编程语言中,我通常会写以下内容:
Ideally, and in some programming languages in normally, I would write the equivalent of the following:
let bar (i:int) : Foo =
match i with
| 1 -> B "one"
| _ -> A i
但是,这不能正确地进行类型检查,给了我一个错误,该表达式应该具有Foo类型,但这里具有B类型".我不明白为什么编译器没有足够的信息来推断匹配表达式的通用超级类型,然后检查通用超级类型是否为"Foo".
However this fails to type check correctly, giving me the error, "This expression was expected to have type Foo but here has type B". I don't understand why the compiler doesn't have enough information to infer a common super type for the match expression and then check that the common super type is 'Foo'.
目前,我被迫为模式匹配中的每种情况提供明确的强制:
At present I am forced to provide an explicit coercion for every case in the pattern match:
let bar2 (i:int) : Foo =
match i with
| 1 -> (B "one") :> Foo
| _ -> (A i) :> Foo
我想避免这种情况.
更多说明
- 直觉表明,这是一个更普遍的问题的结果.我本来会认为,与模式匹配一样普遍,或者如果语句也表现出相同的属性,那么就会有类型检查规则来说明常见的超类型.
- 在有人建议之前,我很高兴,如果A或B是对象表达式,那是可行的,但是我的真实示例是在C#类的实例中创建它们为普通类的实例.
- 我是否有一种方法可以声明函数以隐式转换类型,例如scala,所以我可以在进行此世代的模块上应用自动转换?
- Intuition suggests that this is a result of a more general issue. I would have thought though that something as common as pattern matching, or if statements which also exhibit the same property, would have a type checking rule to account for common super types.
- Before anyone suggests - I appreciate that if A or B were Object Expressions this would work, but my real example is creating instances of C# classes where they are normal classes.
- Is there a way for me to declare functions to implicitly convert types, as for example scala has, so I could apply automatic conversions for the module where I'm doing this generation?
感谢您对此事的帮助.
推荐答案
我会使用upcast
,la
[<AbstractClass>]
type Foo () =
abstract member Value : unit -> string
type A (i:int) =
inherit Foo ()
override this.Value () = i.ToString()
type B (s) =
inherit Foo ()
override this.Value () = s
let bar2 i : Foo =
match i with
| 1 -> upcast B "one"
| _ -> upcast A i
您仍然必须将其添加到每个分支,但这通常比强制转换为类型更可取,因为类型名通常长20或30个字符(MyNamespace.ThisThingy
),而upcast
仅6个字符.
You still have to add it to every branch, but this is often preferable to casting to the type, since often the typename is like 20 or 30 characters long (MyNamespace.ThisThingy
), whereas upcast
is just 6 characters.
但是,简单来说,语言规则不允许其他任何事情,所有分支的类型必须相等.
But, briefly, the language rules don't allow for anything else, the types of all the branches have to be equal.
这篇关于如何在F#模式匹配中隐式转换为常见的超级类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!