为什么带有显式类型注释的值在这里泛化?

Why is a value with an explicit type annotation generalized here?

提问人:Timo 提问时间:12/19/2020 更新时间:12/26/2020 访问量:78

问:

我在模块范围的 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:值限制。当以下情况时,该值已被推断为具有泛型类型:要么将参数设置为显式,要么,如果您不希望它是泛型的,则添加类型注释。getValval getVal: (HttpFunc -> '_a -> Task<HttpContext option>)'_a :> HttpContextgetVal

我知道它本质上泛化为可以转换为 HttpContext 的东西。为什么会这样?为什么只针对这个参数而不是?ctx: HttpContextnext: HttpFunc

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

F# 值限制

评论

0赞 Fyodor Soikin 12/19/2020
你确定这正是你正在使用的代码吗?难道是您在进行更改后忘记重新编译模块了吗?
0赞 Timo 12/19/2020
@FyodorSoikin我在这里发布验证之前进行了完全重建,则代码是从我的源文件中复制粘贴的(除了一些名称更改)。
0赞 Arshia001 12/19/2020
尝试到处添加类型注释,看看会发生什么。在这种情况下,我猜类型注释应该可以做到这一点。asJsonResponse

答:

0赞 Valeriu Seremet 12/26/2020 #1

如果您添加类型注释,它就会编译:

let getVal: HttpFunc -> HttpContext -> Task<HttpContext option> =
    someFuncThatReturnsTaskOfMyType() |> asJsonResponse

或者添加显式参数:

let getVal f = asJsonResponse (someFuncThatReturnsTaskOfMyType()) f

简单的答案是 F# 编译器的类型推断机制并不完美。你可以在这里读到这个 :

F# 编译器尝试猜测最通用的类型 会适合,但在某些情况下,编译器会觉得代码是 模棱两可,而且,即使它看起来像是在猜测类型 正确地,它需要你更具体

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

MSDN 自动泛化 F# 中有一些示例

通常,当您需要 构造为泛型,但编译器信息不足 来概括它,或者当你无意中省略了足够的类型时 非泛型结构中的信息。