There are two problems with your approach. First of all, when you use an underscore in the definition of your function, that's the same as using a fresh type variable, so your definition is equivalent to the following:
let convert (v: float<'u>) = //'
match v with
| :? float<m> -> v / 0.1<m>
| :? float<m/s> -> v / 0.2<m/s>
| _ -> failwith "unknown"
What the error message is telling you is that the compiler know that v
is of type float<'u>
, and float<'u>
has no proper subtypes, so there's no point in doing a type test to determine if it's a float<m>
or any other type.
You might try to get around this by first boxing v
into an object and then doing a type test. This would work, for instance, if you had a list<'a>
and wanted to see if it were a list<int>
, because full type information about generic objects is tracked at runtime including generic type parameters (notably, this is different from how some other runtimes like Java's work). Unfortunately, F# units of measure are erased at runtime, so this won't work here - there is no way for the system to infer the correct measure type given a boxed representation, since at runtime the value is just a plain float
- F#'s system for units of measure is actually quite similar in this respect to how Java handles generic types.
As an aside, what you're trying to do seems quite suspect - functions which are generic in the unit of measure shouldn't do different things depending on what the measure type is; they should be properly parametric. What exactly are you trying to achieve? It certainly doesn't look like an operation which corresponds to physical reality, which is the basis for F#'s measure types.