Il motivo per cui si sta vedendo questo comportamento è perché F # non definisce (~%)
con vincoli statici, come la maggior parte degli operatori di livello superiore. È definito come una funzione Quotations.Expr<'a> -> 'a
. Pertanto, la funzione (~%)
(che è un alias per op_Splice
) definita al tipo T
non viene risolta dagli utilizzi dell'operatore (~%)
di livello superiore.
È possibile vedere questo dal seguente interazione 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.
Così se ridefiniamo il livello superiore (~%)
operatore come segue, allora il vostro esempio verrà compilato senza errori:
let inline (~%) (x : ^a) = (^a : (static member op_Splice : ^a -> 'b) (x))
ma si noti che lo splicing delle quotazioni non funzionerà più:
let x = <@ 3 @>
<@ %x @>
----^
error FS0001: The type 'Expr<int>' does not support the operator '~%'
perché la definizione originale di (~%)
viene trattata appositamente dal compilatore per lo splicing delle quotazioni. Infatti, è possibile see nelle firme Expr
e Expr<'T>
che tali tipi non definiscono alcun operatore, per non parlare di op_Splice
.
È possibile visualizzare risultati simili con &&
e ||
operatori infissi. Che può essere ridefinito (mappatura su op_BooleanAnd
e op_BooleanOr
), ma a meno che non lo siano, sono trattati in modo speciale dal compilatore.
fonte
2012-05-06 17:16:46