La razón por la que usted está viendo este comportamiento se debe a que F # no define (~%)
con restricciones estáticas como la mayoría de los operadores de primer nivel. Se define como una función Quotations.Expr<'a> -> 'a
. Por lo tanto, la función (~%)
(que es un alias para op_Splice
) que definió en el tipo T
no se resuelve con los usos del operador de nivel superior (~%)
.
Esto se puede ver por la siguiente interacción FSI:
> <@ (~%) @>;;
<@ (~%) @>;;
^^^^^^^^^^
C:\Users\Stephen\AppData\Local\Temp\stdin(5,1): error FS0030: Value restriction. The value 'it' has been inferred to have generic type
val it : Expr<(Expr<'_a> -> '_a)>
Either define 'it' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
Así, si volvemos a definir el nivel superior (~%)
operador de la siguiente manera, a continuación, su ejemplo se compilará sin error:
let inline (~%) (x : ^a) = (^a : (static member op_Splice : ^a -> 'b) (x))
pero tenga en cuenta que el empalme de cotización ya no funcionará:
let x = <@ 3 @>
<@ %x @>
----^
error FS0001: The type 'Expr<int>' does not support the operator '~%'
es porque la definición original de (~%)
es tratada especialmente por el compilador para el empalme de comillas. De hecho, puede see en las firmas Expr
y Expr<'T>
que esos tipos no definen ningún operador en absoluto, y mucho menos op_Splice
.
Puede ver resultados similares con &&
y ||
operadores de infijo. Que se puede redefinir (mapeando a op_BooleanAnd
y op_BooleanOr
), pero a menos que lo estén, son tratados especialmente por el compilador.