Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a function that only accepts int32 or int64

Tags:

f#

How do I define a function in F# f that only accepts an argument x which is restricted to be of type int32 or int64 ?

like image 312
Carlo V. Dango Avatar asked Dec 18 '22 19:12

Carlo V. Dango


2 Answers

Here's a way is to restrict it at compile time. First create the generic version of your function:

let inline twice x = x + x

Then restrict it for the desired types by using overload resolution and static member constraints:

type T = T with
    static member ($) (T, x:int  ) = twice x
    static member ($) (T, x:int64) = twice x

let inline restrictedTwice x = T $ x

Tests:

restrictedTwice 4  //val it : int = 8

restrictedTwice 5L //val it : int64 = 10L

restrictedTwice 5u // doesn't compile
like image 73
Gus Avatar answered Mar 04 '23 10:03

Gus


Overloading

If you can live with defining the function as a class method, you can use normal .NET method overloading:

type Foo =
    static member Bar (x : int)   = sprintf "32-bit integer: %i" x
    static member Bar (x : int64) = sprintf "64-bit integer: %i" x

FSI examples:

> Foo.Bar 42;;
val it : string = "32-bit integer: 42"
> Foo.Bar 42L;;
val it : string = "64-bit integer: 42"

Discriminated unions

If you need the function to be a let-bound function, you can't use method overloading. Instead, you can define a discriminated union that constrains the input options to either int or int64:

type DUInt =
| NormalInt of int
| BiggerInt of int64

You should probably come up with some better names, but I chose to avoid Int32 and Int64 because it would make the code difficult to read, as the System namespace also defines these names as types.

With this discriminated union, you can write a function that take a value of that type as input:

let foo = function
    | NormalInt x -> sprintf "32-bit integer: %i" x
    | BiggerInt x -> sprintf "64-bit integer: %i" x

This function has the type DUInt -> string.

FSI examples:

> foo (NormalInt 42);;
val it : string = "32-bit integer: 42"
> foo (BiggerInt 42L);;
val it : string = "64-bit integer: 42"
like image 31
Mark Seemann Avatar answered Mar 04 '23 08:03

Mark Seemann