Reputation: 13
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
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