Problem Summary
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.
Example
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
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
I would like to avoid this.
Further Notes
- 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?
Thanks for any help on this matter.
I would use
upcast, a laYou 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), whereasupcastis just 6 characters.But, briefly, the language rules don’t allow for anything else, the types of all the branches have to be equal.