【问题标题】:Value restriction when there are no generic parameters没有泛型参数时的值限制
【发布时间】:2012-03-13 21:26:58
【问题描述】:

我在以下代码中得到let makeElem 的值限制错误:

let elemCreator (doc: XmlDocument) = 
    fun name (value: obj) ->
        let elem = doc.CreateElement(name)
        match value with
        | :? seq<#XmlNode> as childs -> 
            childs |> Seq.iter (fun c -> elem.AppendChild(c) |> ignore)
            elem
        | _ -> elem.Value <- value.ToString(); elem

let doc = new XmlDocument()
let makeElem = elemCreator doc

如果从elemCreator 返回的匿名函数没有任何泛型参数,为什么会出现值限制错误?

编译器声明 makeElem 的推断类型是(string -&gt; 'a -&gt; XmlNode)。但是,如果我将第二个参数声明为obj,为什么它会将第二个参数推断为'a

【问题讨论】:

    标签: f# value-restriction


    【解决方案1】:

    相信这可能是“预期的”行为(尽管在这种情况下很不幸),这是编译器的泛化和浓缩过程的结果。考虑 Tomas 的例子:

    let foo (s:string) (a:obj) = a
    

    如果你要定义

    let bar a = foo "test" a
    

    然后编译器将推断类型bar : 'a -&gt; obj,因为它概括了第一个参数的类型。在你的情况下,你有相当于

    let bar = foo "test"
    

    所以bar 是一个值而不是一个句法函数。编译器基本上执行相同的推理过程,但现在应用了值限制。在您的情况下,这很不幸,因为这意味着您必须使用类型注释显式注释 makeElem(或使其成为句法函数)。

    【讨论】:

      【解决方案2】:

      这对我来说似乎是一个意外的行为。可以使用更简单的函数来演示:

      let foo (s:string) (a:obj) = a
      let bar = foo "bar"             // Value restriction
      

      一种可能的解释是 F# 编译器允许您调用一个函数,该函数采用某种类型的参数和任何子类型的参数。因此,您可以调用foo "hi" (new A()),而无需将A 显式转换为obj(前一段时间需要这样做)。

      这种隐式转换可能意味着编译器实际上将 bar 解释为如下内容:

      let bar a = foo "bar" (a :> obj)
      

      ...所以它认为这个论点是通用的。无论如何,这只是一个推测,因此您可以尝试将其作为错误报告发送给 microsoft dot com 上的 fsbugs

      【讨论】:

      • 我刚刚在 fsbugs 发送了错误请求,感谢您的建议!如果他们给我回复,我会告诉你的。
      • 我认为这与obj 有关,而不是一般的多态性。我不明白这是一个错误。
      【解决方案3】:

      (以下仅基于观察。)

      如果您有一个函数obj -&gt; 'a,则不会使用对该函数的调用来推断/求解其参数的类型。插图:

      let writeLine (arg: obj) = System.Console.WriteLine(arg)
      

      writeLineobj -&gt; unit

      let square x = 
        writeLine x
        x * x
      

      在上述函数中,x 被推断为int,因为(*)。如果一个类型可以被obj 约束,那么这个函数将不起作用(x 在使用(*) 之前会被推断为obj,这会导致错误如下:type obj 不支持运算符(*))。

      我认为这种行为是一件好事。无需将类型限制为obj,因为每种类型都已隐式转换为obj。这使您的程序更通用,并提供与 .NET BCL 更好的互操作性。

      简而言之,obj 与类型推断无关(耶!)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-26
        • 2021-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-20
        相关资源
        最近更新 更多