The problem here is that type x is actually a string . Having added that it comes from Console.ReadLine , what information is stored in this line, it can only be determined at runtime. This means that you cannot use pattern matching or pattern matching with coercion here.
But you can use Active templates . As the fact that the actual data is stored in x is known only at runtime, you need to parse the string and see what it contains.
Suppose you are expecting a float , but you cannot be sure, as the user can enter whatever he wants. We will try to parse our line:
let my_sqrt x = let success, v = System.Single.TryParse x // the float in F
But this does not compile:
This expression should have been of type float32, but there is a line of type
The problem is that the compiler deduced a function to return float32 based on the sqrt (System.Single.Parse(x)) expression sqrt (System.Single.Parse(x)) . But then, if x does not parse the float, we intend to simply return it, and since x is a string, we have inconsistency here.
To fix this, we need to convert the sqrt result to a string:
let my_sqrt x = let success, v = System.Single.TryParse x if success then (sqrt v).ToString() else x
Well, this should work, but it does not use pattern matching. So let's define our โactiveโ pattern, since we cannot use regular pattern matching here:
let (|Float|_|) input = match System.Single.TryParse input with | true, v -> Some v | _ -> None
Basically, this pattern will only match if input can be correctly parsed as a floating point literal. Here's how you can use it in your initial implementation of the function:
let my_sqrt' x = match x with | Float f -> (sqrt f).ToString() | _ -> x
This is very similar to your function, but note that I still need to add the .ToString() bit.
Hope this helps.