【问题标题】:simple F# run-time generic function with type constraint can't be resolved无法解析具有类型约束的简单 F# 运行时泛型函数
【发布时间】:2012-06-08 19:43:17
【问题描述】:

我有一个带有一个通用参数的基本函数:

let func<'T> (x:'T when 'T : (static member op_Explicit: 'T -> float) ) =
   float x

为什么我会收到错误:“声明的类型参数 'T 不能在此处使用,因为类型参数无法在编译时解析”

在这个例子中,我提供了一个通用参数并限制它能够显式地转换为浮点数,并且所有的函数都被转换为浮点数,那么问题是什么?我已经阅读了所有与 F# 中的泛型相关的 MSDN 文档,但它们似乎只是绕圈子,与我在 Visual Studio 中看到的行为不符。据我了解,使用单引号语法'T 是针对运行时泛型,而不是编译时泛型。

这让我想到了另一个问题。我经常看到'T^T 混合在一起的语法,无论有没有inline。这与有关这些语法定义的 MSDN 文档背道而驰。我错过了什么吗?

此外,从文档看来,'T 类型的 op_Explicit 约束似乎应该能够在没有任何类型注释的情况下自动推断:

let func x =
   float x

但在这种情况下,x 的类型被推断为int

【问题讨论】:

  • @ildjarn,我已经能够让inline 或“静态解析”参数类型以类似的方式工作,但在这个问题中,我问的是正确的语法标准运行时类型解析。
  • 我不明白你在说什么。如果没有inline,则不能使用静态解析的类型参数。 float 需要静态解析的类型参数,因此任何要传递给 float 的函数也需要内联,除非您愿意将使用限制为单一类型。
  • 我想我不明白你说“浮点需要静态解析的类型参数”是什么意思。如果我将 x 限制为仅具有 op_Explicit: 'T -&gt; float 的那些类型,那么在运行时或编译时解析确切的类型有什么关系?
  • 因为该约束(在 F# 术语中)可以在编译时进行。 :-] 你可以使用反射来达到同样的效果,但是没有直接的语法,而且性能也不会很好。
  • 我明白你现在在说什么,我已经添加了一个答案来总结。

标签: generics f# inline type-inference


【解决方案1】:

这里有一个可能会有所帮助的快速摘要。

您使用inline^T 以及成员约束来编写怪异的代码'为所有类型T 具有此ad-hoc API 集';这是不能直接在 .NET 中编写的代码(例如,您不能用 C# 编写它),它必须是 inline,因为 F# 编译器可以在每个单独的调用站点内联/硬编码特定类型。这是一项非常高级的功能,因此您不太可能找到太多关于它的文档/示例(而且错误诊断并不总是很好)。

您将'T 用于普通泛型,例如您在 C# 中所做的通常通用的事情。这是主线场景。

请注意,在这两种情况下,通常可以(/更好/更容易)让 F# 为您推断类型和泛型,而不是拼写出来。例如

let inline f x = float x

Visual Studio 中 f 上的悬停提示表明已推断出适当的约束。

【讨论】:

    【解决方案2】:

    感谢@ildjarn,我找到了答案:

    来自http://msdn.microsoft.com/en-us/library/dd548046

    静态解析类型参数主要与成员约束结合使用,这些约束允许您指定类型参数必须具有特定成员或多个成员才能使用。没有办法通过使用常规的泛型类型参数来创建这种约束。

    似乎Visual Studio应该给出不同的错误,然后,例如: “成员约束不能在此处使用,因为 'T 不是静态解析的类型”或 “成员约束只能与静态解析的类型参数一起使用。”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多