Джек ответ правильный. Я добавлю немного больше контекста. (%%)
- это оператор нетипизированного соединения (то есть он вставляет Quotations.Expr
в другую типизированную или нетипизированную цитату), в то время как (%)
- это типизированный оператор соединения (то есть, он склеивает Quotations.Expr<'t>
для некоторого 't
в другую типизированную или нетипизированную цитату). (a : ty)
- это просто аннотация типа, поэтому (%%row : float[])
указывает, что когда row
вставляется в цитату, результатом является float[]
. Без этой аннотации %%row
может быть значением любого типа, и компилятор не сможет определить, что мы имеем в виду под индексатором .[]
(так же, как он не может определить тип 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
принимает 'a[]
в качестве аргумента, и мы добавляем аннотацию типа, которая указывает, что результатом является float, поэтому F # выведет, что %%row
является float[]
.