I'm trying to define a "quasi-generic" function. Rather than making it entirely generic, I'd like it to work only for the "integer" types (i.e. byte, sbyte, int16, uint16, int, uint32, int64, uint64, bigint).
How can I put this into a type annotation on the function definition? To clarify, how would I rewrite the following code to actually work (using only 3 types presumably without loss of generalization):
let square (x: int|int64|bigint) =
x * x
First of all, there is no way to resolve such a type constraint using standard .NET generics at runtime.
F# does allow you to express a limited form of such constraints by resolving them at compile time and inserting the proper function call inline. This makes use of statically resolved type parameters.
It's quite simple for the case you have described, you can just write:
let inline square x = x * x
This will work for any type 'T
which has the *
operator defined.
You can also apply specific static/member constraints explicitly but this requires more ugly syntax, e.g.
let inline id item =
( ^T : (member Id : int) (item))
This example function will operate on any type that exposes an Id
property of type int
.
Update: Based on the specific use case you're describing, you really type-classes. Those don't really exist in F# (aside from a few hard-coded examples) but you can simulate them using a marker type and member constraints, here is an example:
type Marker =
|Marker
static member Multiply (marker : Marker, numX : int, numY : int) =
numX * numY
static member Multiply (marker : Marker, numX : int64, numY : int64) =
numX * numY
let inline multiply x y =
((^T or ^U) : (static member Multiply : ^T * ^U * ^U -> ^S) (Marker, x, y))
multiply 5 7
multiply 5L 7L
Notice this lets you specify the exact types you want to allow the functionality on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With