Question

In the MiniCsvTypeProvider, I see the following line of code:

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

with GetterCode type is : Quotations.Expr list -> Quotations.Expr :

I don't really know what the lambda fun is doing....

  • it matches its input with a single element array, binding it to a variable named 'row' , of type Quotations.Expr from the GetterCode signature.

  • it creates a code quotation in return

  • inside the code quotation, it uses %%row:float[] and I don't know what this means : is that a Float [] type constraint for untyped code quotations ?
Was it helpful?

Solution

Jack's answer is correct. I'll add a bit more context. (%%) is the untyped splice operator (that is, it splices a Quotations.Expr into another typed or untyped quotation), while (%) is the typed splice operator (that is, it splices a Quotations.Expr<'t> for some 't into another typed or untyped quotation). (a : ty) is just a type annotation, so (%%row : float[]) indicates that when row is spliced into the quotation the result is a float[]. Without this annotation, %%row could be a value of any type, and the compiler would be unable to infer what we mean by the .[] indexer (just as it can't infer the type of arr in fun arr i -> arr.[i]).

In case it's helpful, here are some alternative ways to express roughly the same thing as <@@ (%%row:float[]).[i] @@>:

  • We can convert the untyped quotation to a typed quotation before splicing:

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

    Here we are using the typed splice operator (%), so the compiler knows that %typedRow is a float[] and that the .[] operator is applicable.

  • We can use a different way of indexing into the array so that F#'s type inference can determine the type of %%row without an annotation:

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

    Here, the Array.get method takes an 'a[] as an argument and we add a type annotation which indicates that the result is a float, so F# will infer that %%row is a float[].

OTHER TIPS

The :float[] is an explicit type annotation (not constraint, which is similar but different); it's saying %%row will produce a value of type float[].

Then by wrapping it in parenthesis, you can use the .[idx] syntax to get an element of the array because the F# compiler infers the type of the value within the parenthesis as float[].

Explicitly specifying a type annotation this way can be a useful way to give the F# compiler a "hint" and resolve type inference errors.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top