Today’s random F# code: Type inference

Today’s random F# code is about type inference. If you like var, default and new() in C#, you might like F# a lot because F# gives you type inference also for function parameters, return types and generics (grey = IDE showing the inferred function signature):

F# type inference examples

This helps with refactoring a lot – but you’ll probably only believe me if you have experienced it. And it’s much less to write and read, which makes me a faster developer.

Feedback

why is int inferred into ‘let add x y’ and not any other kind of numeric type, like, e.g. decimal? And why does it even need to be a numeric type, as with operator overloads you could also + custom types..?

Beat Walti

Int is inferred because the compiler falls back to int for + when there is no further information about the types – e.g. through usage of add.


Type inference is like polish vodka. Should be served in *very* tiny cups. I made mistakes when I was younger, got world-ending headaches and learnt moderation ever since.

fabienbk

My experience is different from fabienbk’s. There are however some drawbacks. If you for example do code reviews outside of the IDE, without type annotations, understanding the code in detail may become much harder. Often, a value is however passed to a module function and that makes the type rather obvious as well. Like:

let work list = list |> List.filter (fun element -> element > 0)

list must be a list of integers by its usage.

But of course, if adding a type annotation helps you, do it.


BTW, I find the way of specifying types in function signatures in F# very inconvenient. It would be so much better if we could just write the signature in the same way that your IDE shows them in grey. Haskell does exactly that and it is awesome.

Alexey Raga

Yes, it is inconvenient that there are two different ways how function signatures are dealt with. It’s also an additional hurdle to take when learning F#: a,b => a * b, fun a b => ‘a -> ‘b -> ‘c.


wait, if “Length” was unique, then type would be inferred?

Eric J. Cartman

I had to check it myself. It doesn’t infer class properties or methods, but it does work with record type properties. Also, the property name doesn’t have to be unique. You can declare two record types and it infers the type further down the file nearest to the function.

Steve Goguen

add could work with int, float or string types, but only one of them. The first time its used determines the actual inferred type. add “a” “b” // ok add 1.0 2.0 // error add 1 2 // error expects string declared as inline works for all cases: let inline add x y = x + y

amieres

Exactly, inlining inlines the function everywhere it is used and therefore the variables can take different forms (types).


This blog post is made possible with the support of Time Rocket, the product this journey is all about. Take a look (German only).

About the author

Urs Enzler

Add comment

By Urs Enzler

Recent Posts