Reputation: 605
In following case
let a = [1]
let f x = x
let b = a |> List.map f
a is an int list. We call List.map so for sure f must be a int->? function. Why is f still typed as 'a ->'a instead of int->int? If this is how type inference (not)works in F# i see little benefits for it.
Is there an workaround without specifying the type for x in f explicitly? Lets imagine x has type (A*B*C list ( D option, E list)))
Also another interesting thing:
open System.Collections.Generic
let d = new Dictionary()
d.[1] ="a"
This does not work unless the "new" keyword is removed.
Upvotes: 0
Views: 371
Reputation: 751
To add a little something to the fine answers already listed here.
There is one circumstance where you will want to not use the generic inferred type. The generic version of f will be slower than the type specific version. But F# has a keyword for taking care of that for you:
let inline f x = x
Which tells the compiler to use the type specific version of any operations you apply to x. The inferred type will remain generic. You will only need this in time critical section of code.
As noted elsewhere, the generic inference is a useful thing and you'll probably grow to like it.
Upvotes: 0
Reputation: 5688
The function f
is typed 'a -> 'a
because it works at every type, not just int
:
> f "foo";;
val it = "foo" : string
> f 0.8;;
val it = 0.8 : float
This an advantage: the generic type 'a -> 'a
gives you the freedom to use f
when it is safe to do so, as opposed to only at the type int -> int
.
Upvotes: 3
Reputation: 233457
Type inferencing works just fine here. f
is inferred as having the type 'a -> 'a
, which means that it'll take a value of the generic type 'a
and return a value of the same generic type 'a
.
In this case, type inferencing kicks in when you use it. Because a
has the type int list
, and because List.map
has the signature ('T -> 'U) -> 'T list -> 'U list
, it can infer types from the expression
let b = a |> List.map f
In this case, the 'T list
argument is a
, so it has the type int list
. This means it now knows that 'T
is int
.
The function passed to List.map
has the general form 'T -> 'U
, but in this case we pass f
, which has the form 'a -> 'a
, which is equivalent to 'T -> 'T
. Because of this, the compiler understands that in this case, 'T
and 'U
are the same types.
This means that it can infer that the return type 'U list
must also be int list
.
Upvotes: 4