Skip to content

Inferred Generics in F#

The first hundred or so pages of Expert F# have been really interesting, the compiler feels so much more advanced than C#. Although I think it has more to do with the nature of functional programming than any deficiency in the C# compiler. The code does not tell the machine how to do something rather it says what needs to be done. Which means the compiler is free to do as it wishes and may compile things to have a broader meaning, so long as the intention of the code is honored.

One of the neat tricks is when a function is automatically inferred to be generic through a process known as Generalization. This occurs when a function does not constrain or use a parameter is such a way that the value must be of a specific type.

Lets start with something that is not Generalized. A function that takes a tuple of two values and subtracts 1 from each value.

> let sub (a,b) = (a-1, b-1);;
val sub : int * int -> int * int

> sub (2,3);;
val it : int * int = (1, 2)

While I cannot explain why the sub function is not generalizable in terms of the rules laid out in the language specification of Generalization, it’s pretty clear what’s happened. Subtracting the integer 1 from each of the tuple values requires that the tuple be of type int * int, i.e. two integers. So the function sub takes a tuple of two integers and returns a tuple of two integers.

Now something that can be generalized, returning the first value in a tuple of two values.

> let getFirst (a,b) = a;;
val getFirst : 'a * 'b -> 'a

> getFirst (1,2);;
val it : int = 1

> getFirst ("a", "b");;
val it : string = "a"

Types are denoted by the token, so the tuplea * “b is a tuple of a value of type a and a value of type b. Because of the generalization getFirst can be called with two integers (1,2) or two strings (”a”, “b”). This is just how the built in fst operator works. It takes a tuple of two values and returns the first (there is also a snd to return the second value).

>fst;;
val it : ('a * 'b -> 'a) = <fun:clo@0_6>

> fst (1,2);;
val it : int = 1

> fst ("a", "b");;
val it : string = "a"

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*