8
votes

When I try to create some class like

type MyType () =
    let func<'T> () = ()

The compiler says that there's an error:

Explicit type parameters may only be used on module or member bindings

But the MSDN says:

A let binding at the module level, in a type, or in a computation expression can have explicit type parameters. A let binding in an expression, such as within a function definition, cannot have type parameters.

Why documentation and compiler say different things?

2
That let probably needs to be member. - leppie
The spec forbids it as well (by omission and more specifically in the grammar) - John Palmer

2 Answers

5
votes

This appears to be a syntactic restriction on let bindings inside a class. However, you can still define a generic local function, you just have to specify the type parameters in type annotations:

type MyType () =
   let func (x : 'T) : 'T = x

I do not think this is explicitly syntactically forbidden by the specification, because the specification says that a class definition has the following structure:

type type-name patopt as-defnopt =
      class-inherits-declopt
      class-function-or-value-defnsopt
      type-defn-elements

and class-or-value-defn is defined as:

class-function-or-value-defn := attributesoptstaticoptlet recopt function-or-value-defns

where function-or-value-defns may be a function definition with explicit type parameters:

function-defn :=
inlineoptaccessopt ident-or-op typar-defnsopt argument-pats return-typeopt = expr

3
votes

To add to Tomas's answer, if you need a type parameter but won't have a value of that type you can use a type with a phantom type parameter. e.g.:

open System

type Foo() =
    member x.PrintType<'T> () = printfn "%s" typeof<'T>.Name

type TypeParameter<'a> = TP

let foo = Foo ()

let callFoo (typeParameter : TypeParameter<'a>) =
    foo.PrintType<'a> ()

callFoo (TP : TypeParameter<string>)
callFoo (TP : TypeParameter<DateTime>)