转换无类型的代码报价?

时间:2012-02-28 08:37:21

标签: f# quotations type-providers

在MiniCsvTypeProvider中,我看到以下代码行:

        let prop = ProvidedProperty(fieldName, fieldTy, GetterCode = fun [row] -> <@@ (%%row:float[]).[i] @@>)
GetterCode类型是: Quotations.Expr list - &gt; Quotations.Expr

我真的不知道lambda 有趣正在做什么......

  • 它将其输入与单个元素数组匹配,将其绑定到名为'row'的变量,其类型为GetterCode签名中的Quotations.Expr。

  • 它会在

  • 中创建代码报价
  • 在代码引用中,它使用%% row:float []而我不知道这意味着什么:是无类型代码引用的Float []类型约束?

2 个答案:

答案 0 :(得分:3)

杰克的回答是正确的。我会添加更多的上下文。 (%%)是无类型拼接运算符(即,它将Quotations.Expr拼接成另一种类型或无类型引号),而(%)是键入的拼接运算符(也就是说,它拼接Quotations.Expr<'t> 1}}对于某些't进入另一种类型或无类型的引用)。 (a : ty)只是一种类型注释,因此(%%row : float[])表示当row拼接到引号中时,结果为float[]。如果没有这个注释,%%row可能是任何类型的值,编译器将无法推断.[]索引器的含义(正如它无法推断{{1}的类型在arr)。

如果它有用,可以使用以下几种方法来表达与fun arr i -> arr.[i]大致相同的内容:

  • 我们可以在拼接之前将无类型报价转换为输入的报价:

    <@@ (%%row:float[]).[i] @@>

    这里我们使用了类型化的拼接运算符let typedRow = Quotations.Expr.Cast<float[]> row <@@ %typedRow.[i] @@> ,因此编译器知道(%)%typedRow并且float[]运算符适用。

  • 我们可以使用不同的方式索引数组,以便F#的类型推断可以确定没有注释的.[]的类型:

    %%row

    这里,<@@ Array.get %%row i : float @@> 方法将Array.get作为参数,我们添加一个类型注释,指示结果是一个浮点数,因此F#将推断'a[]是一个{ {1}}。

答案 1 :(得分:2)

:float []是一个显式类型注释(不是约束,它是相似但不同的);它说%% row将产生float []类型的值。

然后通过将其包装在括号中,您可以使用。[idx]语法来获取数组的元素,因为F#编译器将括号内的值的类型推断为float []。

以这种方式明确指定类型注释可以是为F#编译器提供“提示”并解决类型推断错误的有用方法。