There are basically 3 approaches to your problem
a) the types you are using already support the operators/methods you want to apply to them
In this case simply add inline
in front of your function and be happy
b) you have full control over the types you are using
That is you can define new members at the function definition without using extension methods. In this case you define a method on each class implementing what you need
type MyInt16 = MyInt16 of int
with
static member Mult(x, y) =
match x,y with
| MyInt16 x', MyInt16 y' -> MyInt16 (x' * y')
type MyInt32 = MyInt32 of int
with
static member Mult(x, y) =
match x,y with
| MyInt32 x', MyInt32 y' -> MyInt32 (x' * y')
and an inline function using generic type constraints with this rather weird looking syntax
let inline mult (x:^T) (y:^T) = (^T : (static member Mult: ^T -> ^T -> ^T) (x, y))
And then you Test
let a = MyInt16 2
let b = MyInt16 3
let c = mult a b
This works. Lets see what happens when we use different types
let d = mult a (MyInt32 3)
The above will get you an error.
c) you don't have full control over your types
That is you can't define methods within the type but you would have to use extension methods. The problem with extension methods is that they can't be used
with inline functions using generic type constraints. In this case you better fall back to the parameter approach I described here
type MultParam =
| MyInt16Param of System.Int16
| MyInt32Param of System.Int32
with
static member op_Implicit(x: System.Int16) = MyInt16Param x
static member op_Implicit(x: System.Int32) = MyInt32Param x
Then define again an inline function with generic constraints that converts your incoming type into your wrapper type
let inline (!>) (x:^a) : ^b = ((^a or ^b) : (static member op_Implicit : ^a -> ^b) x)
and add your implementation. This time a bit wordier as we need to use pattern matching
let inline mult' (x: ^T) (y: ^T) : ^T =
let x' = !> x
let y' = !> y
let r =
match x', y' with
| MyInt16Param x'', MyInt16Param y'' -> x'' * y'' |> box
| MyInt32Param x'', MyInt32Param y'' -> x'' * y'' |> box
| _ -> failwith "Not possible"
r :?> _
Now let's test again
let e = mult' (int16(2)) (int16(3))
This works. Lets see what happens when we use different types
let f = mult' (int16(2)) (int32(3))
Error again as it should be.
Option b) is basically an emulation of Haskells type class feature where as
option c) is closer to OCamls polymorphic variants