akaphenom
akaphenom

Reputation: 6888

F# List of functions

I am trying to have a list of functions, but seem to be coming up empty handed. The basic code is something like this:

let doSomething var  =
    var

let doSomething2 var  =
    var

let listOfStuff = [doSomething; doSomething2]

and I am getting the following exception:

Error 2 Value restriction. The value 'listOfStuff' has been inferred to have generic type val queue : ('_a -> '_a) list Either define 'queue' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation. C:\fsharp\SentimentFramework\TradeSignalProcessor\Program.fs 16 9 TradeSignalProcessor

I tried adding the [<GeneralizableValue>] attribute but that didn't work...

Upvotes: 1

Views: 1902

Answers (4)

Johan Kullbom
Johan Kullbom

Reputation: 4243

You have ancountered 'the value restriction'. You are not allowed to define generic 'values' like the listOfStuff-array.

There are a few previous questions on this subject that you might find useful and Microsoft writes about this under the topic "Automatic Generalization".

Edit: Dmitry Lomov has written a great article on the subject here: "Finer Points of F# Value Restriction".

Upvotes: 1

kvb
kvb

Reputation: 55184

As others have noted, giving explicit types to your functions or to your list will resolve your issue. The reason that this occurs is that functions can have generic types, but (generally speaking) values can't. The compiler has inferred that both of your functions have type 'a -> 'a for any type 'a. This means that your list would have type ('a -> 'a) list, which is a generic type and is invalid for a value. Specifying an explicit type such as let listOfStuff : (int -> int) list = ... will resolve the ambiguity.

Having said that, note that I can't reproduce this exact issue in the latest version of the compiler (F# 2.0.0.0). It appears that list expressions can be generalized (presumably since they are side-effect free). However I see an analogous error when I use an array expression instead.

Upvotes: 3

Tejs
Tejs

Reputation: 41246

You want a list, composed of functions? I would think it would go like this:

let f x = x + 1
let g x = x + 1

let listOfFunc = [f; g]

If you need to specify the parameter, just remember to use the type notation:

let f (x:string) = x + "1"

Upvotes: 3

Shaun
Shaun

Reputation: 4018

Lists should all have the same type. Try using a tuple for this instead.

...and try doing as the error suggests. Give your inputs a type at the very least.

Upvotes: 0

Related Questions