Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mimic F# compiler type checking?

Tags:

f#

In F#, I can write a function (fun x -> x * x) and confirm it has type int->int because the following code compiles:

let typeCheck<'T> (x:'T) = ()
typeCheck<int->int> (fun x -> x*x)

On the other hand, GetType for this function doesn't agree with typeof<int->int>:

> (fun x -> x*x).GetType() = typeof<int -> int>
val it : bool = false

If not GetType() and typeof, what functions can I call to mimic the type-checking done by the compiler?

like image 853
Paul Orland Avatar asked Dec 31 '22 21:12

Paul Orland


2 Answers

The reason why GetType of a specific lambda function is not the same as typeof<int -> int> is that the F# compiler generates a new class for the function which inherits from int -> int. In other words, the types are not the same, but the type you get via GetType inherits from int -> int.

You can check for this easily using IsAssignableFrom. The following is true:

typeof<int -> int>.IsAssignableFrom((fun x -> x*x).GetType())
like image 165
Tomas Petricek Avatar answered Jan 10 '23 00:01

Tomas Petricek


You can use the :? operator to check based on type. I boxed it because (int -> int) is a sealed type.

F# Why can't I use the :? operator in F# interactive?

> let f = box (fun x -> x*x);;
val f : obj
> f :? (int -> int);;
val it : bool = true

If you wanted to build your typecheck function you could use this. A 'T and a thing of type 'T, they would always have the same type so I made x an object here, and you can box it before looking at it. However you probably don't need to do this, so if you're new to F# you may be working harder than you need to.

let typeCheck<'T> (x: obj) =
    x :? 'T 
//which is the same as
x :? (int -> int)
//so you probably don't need to define your own :)
like image 24
VoronoiPotato Avatar answered Jan 10 '23 01:01

VoronoiPotato