Question

As I know, explicit type parameters in value definitions is a one way to overcome "value restriction" problem.
Is there another cases when I need to use them?

Upd: I mean "explicitly generic constructs", where type parameter is enclosed in angle brackets, i.e.

let f<'T> x = x
Was it helpful?

Solution 2

This would likely be rare, but when you want to prevent further generalization (§14.6.7):

Explicit type parameter definitions on value and member definitions can affect the process of type inference and generalization. In particular, a declaration that includes explicit generic parameters will not be generalized beyond those generic parameters. For example, consider this function:

let f<'T> (x : 'T) y = x

During type inference, this will result in a function of the following type, where '_b is a type inference variable that is yet to be resolved.

f<'T> : 'T -> '_b -> '_b

To permit generalization at these definitions, either remove the explicit generic parameters (if they can be inferred), or use the required number of parameters, as the following example shows:

let throw<'T,'U> (x:'T) (y:'U) = x

Of course, you could also accomplish this with type annotations.

OTHER TIPS

Polymorphic recursion is another case. That is, if you want to use a different generic instantiation within the function body, then you need to use explicit parameters on the definition:

// perfectly balanced tree
type 'a PerfectTree = 
| Single of 'a
| Node of ('a*'a) PerfectTree

// need type parameters here
let rec fold<'a,'b> (f:'a -> 'b) (g:'b->'b->'b) : 'a PerfectTree -> 'b = function
| Single a -> f a
| Node t -> t |> fold (fun (a,b) -> g (f a) (f b)) g

let sum = fold id (+)

let ten = sum (Node(Node(Single((1,2),(3,4)))))

Most obvious example: write a function to calculate the length of a string.

You have to write:

let f (a:string) = a.Length

and you need the annotation. Without the annotation, the compiler can't determine the type of a. Other similar examples exist - particularly when using libraries designed to be used from C#.

Dealing with updated answer:

The same problem applies - string becomes A<string> which has a method get that returns a string

let f (a:A<string>) = a.get().Length
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top