3
votes

Assuming I have these types (forgive the C# syntax, I'm new to F#):

interface I { }
class A { }
class B : A, I { }

In C# I can do this:

A a = …
bool isI = a is I;

However, in F#, having this:

let a : A = ...

I know that a may contain an instance of B and implement I. However, this results in a compile error saying A is not compatible with I:

let isI = a :? I

However, this works:

let isI = a :> obj :? I

How come? a :? I is neither an upcast nor a downcast, sure. But how does it work with obj? Do interfaces somehow count as object subclasses?

1

1 Answers

4
votes

I think the answer is hinted in the docs:

Returns true if the value matches the specified type (including if it is a subtype); otherwise, returns false (type test operator).

If you refer to the spec in 7.9 Dynamic Type-Test Patterns, it confirms this is a compile-time constraint:

An error occurs if type cannot be statically determined to be a subtype of the type of the pattern input

The interface is 'higher' in the hierarchy, it's not A or a subtype of A.

In mucn the same way, this doesn't compile either:

let isObj = a :? obj

By upcasting to obj first, you can then check if the type is I, as this is a subtype of obj.