Some functions in the List module fail when the argument is an empty list. List.rev is an example. The problem is the dreaded Value Restriction.
I met the same problem while trying to define a function that returns a list with all but the last element of a list:
let takeAllButLast (xs: 'a list) =
xs |> List.take (xs.Length - 1)
The function works well with nonempty lists, but a version that would handle empty lists fails:
let takeAllButLast (xs: 'a list) =
if List.isEmpty xs then []
else xs |> List.take (xs.Length - 1)
takeAllButLast []
error FS0030: Value restriction. The value 'it' has been inferred to have generic type
val it : '_a list, etc.
I tried several things: making it an inline function, not specifying a type for the argument, specifying a type for the returned value, making the function depend on a type argument, and using the Option type to obtain an intermediate result later converted to list<'a>. Nothing worked.
For example, this function has the same problem:
let takeAllButLast<'a> (xs: 'a list) =
let empty : 'a list = []
if List.isEmpty xs then empty
else xs |> List.take (xs.Length - 1)
A similar question was asked before in SO: F# value restriction in empty list but the only answer also fails when the argument is an empty list.
Is there a way to write a function that handles both empty and nonempty lists?
Note: The question is not specific to a function that returns all but the last element of a list.