Vous lancez une citation de code non typée ?
-
13-11-2019 - |
Question
Dans le MiniCsvTypeProvider, je vois la ligne de code suivante :
let prop = ProvidedProperty(fieldName, fieldTy, GetterCode = fun [row] -> <@@ (%%row:float[]).[i] @@>)
avec le type GetterCode est : Liste Quotations.Expr -> Quotations.Expr :
Je ne sais pas vraiment ce que le lambda amusant fait....
il fait correspondre son entrée avec un tableau d'éléments uniques, en le liant à une variable nommée 'row' , de type Quotations.Expr à partir de la signature GetterCode.
il crée une citation de code en retour
- à l'intérieur de la citation de code, il utilise %%row:float[] et je ne sais pas ce que cela signifie : est-ce une contrainte de type Float [] pour les citations de code non typées ?
La solution
La réponse de Jack est correcte.J'ajouterai un peu plus de contexte. (%%)
est l'opérateur d'épissage non typé (c'est-à-dire qu'il épisse un Quotations.Expr
dans une autre citation tapée ou non), tandis que (%)
est l'opérateur d'épissage typé (c'est-à-dire qu'il épisse un Quotations.Expr<'t>
pour certains 't
dans une autre citation tapée ou non). (a : ty)
est juste une annotation de type, donc (%%row : float[])
indique que lorsque row
est intégré à la citation, le résultat est un float[]
.Sans cette annotation, %%row
pourrait être une valeur de n’importe quel type, et le compilateur serait incapable de déduire ce que nous entendons par .[]
indexeur (tout comme il ne peut pas déduire le type de arr
dans fun arr i -> arr.[i]
).
Au cas où cela pourrait être utile, voici quelques façons alternatives d'exprimer à peu près la même chose que <@@ (%%row:float[]).[i] @@>
:
Nous pouvons convertir la citation non typée en citation typée avant l'épissage :
let typedRow = Quotations.Expr.Cast<float[]> row <@@ %typedRow.[i] @@>
Ici, nous utilisons l'opérateur d'épissure typé
(%)
, donc le compilateur sait que%typedRow
est unfloat[]
et que le.[]
l’opérateur est applicable.Nous pouvons utiliser une manière différente d'indexer dans le tableau afin que l'inférence de type de F# puisse déterminer le type de
%%row
sans annotation :<@@ Array.get %%row i : float @@>
Ici le
Array.get
la méthode prend un'a[]
comme argument et nous ajoutons une annotation de type qui indique que le résultat est un float, donc F# déduira que%%row
est unfloat[]
.
Autres conseils
Le: float [] est une annotation de type explicite (non contrainte, qui est similaire mais différente);Il dise %% la ligne produira une valeur de type float [].
Puis, en l'enveloppant entre parenthèses, vous pouvez utiliser la syntaxe. [IDX] pour obtenir un élément du tableau car le compilateur F # déduit le type de valeur dans la parenthèse comme float [].
spécifiant explicitement une annotation de type de cette façon peut être un moyen utile de donner au compilateur F # un "indice" et de résoudre des erreurs d'inférence de type.