Powodem widzisz to zachowanie jest ponieważ F # nie definiuje (~%)
ze statycznych ograniczeń jak większość operatorów najwyższego poziomu. Jest zdefiniowany jako funkcja Quotations.Expr<'a> -> 'a
. W związku z tym funkcja (która jest aliasem dla op_Splice
) zdefiniowana dla typu T
nie została rozstrzygnięta przez użycie operatora najwyższego poziomu (~%)
.
Widać to brzmienie interakcji 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.
Jeśli więc przedefiniować najwyższego poziomu (~%)
operatora jak następuje, wówczas przykładem będzie skompilować bez błędów:
let inline (~%) (x : ^a) = (^a : (static member op_Splice : ^a -> 'b) (x))
ale zwróć uwagę, że łączenie ofert nie będzie już działać:
let x = <@ 3 @>
<@ %x @>
----^
error FS0001: The type 'Expr<int>' does not support the operator '~%'
ponieważ oryginalna definicja (~%)
jest traktowana przez kompilator specjalnie do składania ofert. Rzeczywiście, można see w sygnaturach Expr
i Expr<'T>
, że te typy nie definiują żadnych operatorów, nie mówiąc o op_Splice
.
Możesz zobaczyć podobne wyniki z operatorami infiksów &&
i ||
. Które można ponownie zdefiniować (mapowanie na op_BooleanAnd
i op_BooleanOr
), ale jeśli nie są, są one traktowane przez kompilator.