F# 为什么带有显式类型注释的值在这里是通用的?

F# 为什么带有显式类型注释的值在这里是通用的?,f#,value-restriction,F#,Value Restriction,我在模块作用域上的let绑定上得到一个VR错误,说它的一个参数是泛型的,但我不知道为什么这个参数首先是泛型的。代码如下: let private asJsonResponse (responseSource: _ Task) = fun (next: HttpFunc) (ctx: HttpContext) -> task { let! consumption = responseSource return! json

我在模块作用域上的let绑定上得到一个VR错误,说它的一个参数是泛型的,但我不知道为什么这个参数首先是泛型的。代码如下:

let private asJsonResponse (responseSource: _ Task) =
    fun (next: HttpFunc) (ctx: HttpContext) ->
        task {
            let! consumption = responseSource
            return! json consumption next ctx
        }

let getVal = someFuncThatReturnsTaskOfMyType() |> asJsonResponse
错误在最后一行:

错误FS0030:值限制。已推断值
getVal
具有泛型类型
val getVal:(HttpFunc->'\u a->Task)
'\u a:>HttpContext
使
getVal
的参数显式,或者,如果不希望它是泛型的,则添加类型注释

我知道它本质上把
ctx:HttpContext
概括为可以转换为
HttpContext
的东西。为什么会发生这种情况?为什么只针对这个参数,而不针对下一个:HttpFunc


HttpContext
是一个类,而
HttpFunc
是一个函数类型,这就是问题所在吗?

如果您添加类型注释:

let getVal: HttpFunc -> HttpContext -> Task<HttpContext option> =
    someFuncThatReturnsTaskOfMyType() |> asJsonResponse
简单的答案是F#编译器的类型推断机制并不完美。您可以阅读以下内容:

F#编译器尝试猜测可能的最通用类型 将适合,但在某些情况下,编译器认为代码是 模棱两可,而且,尽管它看起来像是在猜测类型 正确地说,它需要你更加具体

有关更具体的详细信息,请参阅以下文档:

有一些例子吗

通常,值限制错误发生在您需要 构造为泛型,但编译器没有足够的信息 泛化它,或者无意中省略了足够的类型 非广义结构中的信息


如果添加类型批注,则会进行编译:

let getVal: HttpFunc -> HttpContext -> Task<HttpContext option> =
    someFuncThatReturnsTaskOfMyType() |> asJsonResponse
简单的答案是F#编译器的类型推断机制并不完美。您可以阅读以下内容:

F#编译器尝试猜测可能的最通用类型 将适合,但在某些情况下,编译器认为代码是 模棱两可,而且,尽管它看起来像是在猜测类型 正确地说,它需要你更加具体

有关更具体的详细信息,请参阅以下文档:

有一些例子吗

通常,值限制错误发生在您需要 构造为泛型,但编译器没有足够的信息 泛化它,或者无意中省略了足够的类型 非广义结构中的信息


你确定这正是你正在使用的代码吗?可能是您在进行更改后忘记重新编译模块了吗?@FyodorSoikin我在这里发布之前进行了完整的重建,以验证代码是从源文件复制粘贴的(除了一些名称更改)。尝试在所有位置添加类型批注,看看会发生什么。在本例中,我猜
asJsonResponse
上的类型注释应该可以完成此操作。您确定这正是您正在使用的代码吗?可能是您在进行更改后忘记重新编译模块了吗?@FyodorSoikin我在这里发布之前进行了完整的重建,以验证代码是从源文件复制粘贴的(除了一些名称更改)。尝试在所有位置添加类型批注,看看会发生什么。在本例中,我猜
asJsonResponse
上的类型注释应该可以做到这一点。