Typecast matters are complicated in F#. Unlike many other languages, F# does not perform implicit upcasts by default. E.g. if class
Derived derives from
Base, and we have
let func( b : Base ) = ... let d : Derived = ...
func(d) will not work. The compiler will complain that type
Derived is not compatible with
Base. This comes as a shock to an object-oriented developer. We must explicitly “upcast” derived class to base class like this:
func (upcast d) or
func (d :> Base). In the former case, F# automatically figures out the destination type, in the latter case we explicitly say what it is.
Alternatively, we can explicitly declare
f as accepting a polymorphic argument:
let func( b : #Base ) = ...
I believe that internally this it implemented via generics. with actual argument type becoming a template parameter.
Overall, F# introduces five typecast operators:
||Automatically deduce destination type T from context and cast x to T. Static type of x must be a subtype of T, or the code will not compile.|
||Cast x to T. Static type of x must be a subtype of T, or the code will not compile.|
||no equivalent||Automatically deduce destination type T from context and cast x to T. Static type of x must be a base class of T, or the code will not compile.|
||If dynamic type of x is T or is derived from T, returns (T)x. Otherwise returns null, even if T is not a class type. Static type of x must be a base class of T, otherwise compilation error occurs.|
||Returns true if dynamic type of x is T or is derived from T, otherwise returns false. Static type of x must be a base class of T, or the code will not compile.|
In addition to the typecast operators, F# uses pattern matching operator
?: [as variable], e.g.
let func (x:Base) = match x with | :? TwiceDerived as td -> td_func td | :? Derived -> 10 | _ -> 0
* There are too many cast operators, and their spelling are quite confusing. I am afraid not many people can intuitively tell what a
:?> might mean.
* Polymorphism is applied inconsistently. E.g. it does not work in function calls by default, but it does work in the
:? operator. In the above example, if actual type of
:? Derived will still work
All of your blog posts about F# contain really serious errors. In this case, your first line of code is wrong (it should be “b : #Base”) and everything that follows is wrong as a consequence.
b: Base is not an error. This line of code works exactly as I describe.
If I declare f(b : #base), the call will indeed become polymorphic, but this is not how it works in other languages.
In other languages you can use derived wherever you use base (Liskov substitution principle).
But it is worth noting that you can have explicit polymorphism via #.
I will edit the post accordingly.