user3665877
user3665877

Reputation: 13

Why does this produce a value restriction exception?

I've created a function that returns a list containing only the even indexes as shown below:

let rec removeOddIdx xs =
    match xs with
    |[] -> []
    |h::t -> (if t.Length % 2 = 0 then 
                [h]@removeOddIdx t
                else 
                removeOddIdx t)

It works fine when I call it:

removeOddIdx [1;2;3;];;

However when I call it with an empty list:

removeOddIdx [];;

I get a Value Restriction exception - how come?
I've read up on value restrictions but I don't understand why it happens in my case.

Here is the precise error message:

Testing.fs(13,1): error FS0030: Value restriction. The value 'it' has been inferred to have generic type

     val it : '_a list

Either define 'it' 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.

Upvotes: 1

Views: 810

Answers (1)

N_A
N_A

Reputation: 19897

The problem you're having is that the compiler doesn't know what type to give the return value. When you pass it [1;2;3] it can infer that the return type is int list, but if you pass it [], what is the type of the return value? It cannot be inferred from the usage, so you get a value restriction error.

One solution is to give the parameter a type like so:

> removeOddIdx ([]:int list);;
val it : int list = []

The other is to make the function specific rather than generic like this:

> let rec removeOddIdx (xs:int list) =
    match xs with
    |[] -> []
    |h::t -> (if t.Length % 2 = 0 then 
                [h]@removeOddIdx t
                else 
                removeOddIdx t);;

val removeOddIdx : xs:int list -> int list

> removeOddIdx [];;
val it : int list = []

Outside of the repl this is unlikely to be an issue since the parameter type is likely to be inferred from elsewhere in your code.

Upvotes: 1

Related Questions