Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Function Type Annotation for Multiple Types

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
like image 366
Talmage Avatar asked Dec 19 '22 07:12

Talmage


1 Answers

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.

like image 157
TheInnerLight Avatar answered Dec 30 '22 11:12

TheInnerLight