1

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

        let prop = ProvidedProperty(fieldName, fieldTy, GetterCode = fun [row] -> <@@ (%%row:float[]).[i] @@>)

GetterCode 类型为:Quotations.Expr 列表 -> Quotations.Expr

我真的不知道 lambda fun在做什么......

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

  • 它创建一个代码引用作为回报

  • 在代码引用中,它使用 %%row:float[] ,我不知道这是什么意思:这是针对无类型代码引用的 Float [] 类型约束吗?
4

2 回答 2

3

杰克的回答是正确的。我将添加更多上下文。(%%)是无类型拼接运算符(即,它将 a 拼接Quotations.Expr到另一个有类型或无类型的引号中),而(%)是有类型的拼接运算符(即,它将 a Quotations.Expr<'t>for some拼接't到另一个有类型或无类型的引号中)。 (a : ty)只是一个类型注释,所以(%%row : float[])表示当row被拼接到引号中时,结果是一个float[]. 如果没有这个注解,%%row它可能是任何类型的值,编译器将无法推断索引器的含义.[](就像它无法推断 in 的类型一样arrfun arr i -> arr.[i]

如果有帮助,这里有一些替代方法可以表达大致相同的内容<@@ (%%row:float[]).[i] @@>

  • 我们可以在拼接前将无类型引用转换为有类型引用:

    let typedRow = Quotations.Expr.Cast<float[]> row 
    <@@ %typedRow.[i] @@>
    

    这里我们使用了类型化的拼接操作符(%),所以编译器知道它%typedRow是 afloat[]并且.[]操作符是适用的。

  • 我们可以使用不同的方式来索引数组,以便 F# 的类型推断可以在%%row没有注释的情况下确定 的类型:

    <@@ Array.get %%row i : float @@>
    

    在这里,该Array.get方法将 an'a[]作为参数,我们添加了一个类型注释,表明结果是一个浮点数,所以 F# 会推断出它%%row是一个float[].

于 2012-02-28T15:35:53.700 回答
2

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

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

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

于 2012-02-28T13:42:18.213 回答