为什么会产生价值限制例外?

时间:2014-05-22 16:00:07

标签: f# functional-programming f#-interactive

我创建了一个函数,它返回一个只包含偶数索引的列表,如下所示:

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

我打电话时工作正常:

removeOddIdx [1;2;3;];;

但是当我用空列表调用它时:

removeOddIdx [];;

我得到了价值限制例外 - 为什么会这样? 我已经阅读了价值限制,但我不明白为什么会发生这种情况。

以下是准确的错误消息:

  

Testing.fs(13,1):错误FS0030:值限制。已推断值'it'具有泛型类型

     

val it : '_a list

     

'it'定义为一个简单的数据术语,使其成为具有显式参数的函数,或者,如果您不打算将其作为泛型,则添加类型注释。

1 个答案:

答案 0 :(得分:1)

您遇到的问题是编译器不知道给返回值的类型。当你传递它[1;2;3]时,它可以推断出返回类型是int list,但如果你传递它[],那么返回值的类型是什么?无法从使用情况中推断出来,因此您会收到值限制错误。

一种解决方案是为参数提供如下类型:

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

另一种方法是使功能具体而不是通用,如下所示:

> 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 = []

在repl之外,这不太可能成为问题,因为参数类型很可能是从代码中的其他地方推断出来的。