2012-05-06 16 views

risposta

5

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.

4

Io non sono esattamente sicuro perché l'operatore % si comporta in questo modo, ma è possibile ridefinire utilizzando globale let vincolante:

let (~%) a = -a 
%10 

Se l'operatore non può essere definito come static membro (non sono sicuro in tal caso, o se mi manca qualcosa), è ancora possibile definire una definizione inline che richiama un membro statico di un oggetto. Questo dovrebbe dare essenzialmente la stessa funzionalità:

// Instead of defining static member '%', we define static member 'Percent' 
type T() =  
    static member Percent(t : T) = t 

// Inline definition of '~%' that calls the static member 'Percent' of an object 
let inline (~%) (x : ^T) = (^T : (static member Percent : ^T -> 'R) (x)) 

// Now you can use the '%t' syntax to invoke the static member 
let t = T()  
let t' = %t 

Contesto: Nel codice F # citazione, è usato per "splicing" di espressioni in un'altra espressione (per costruire un'espressione che è composto da un altro, precedentemente definiti espressione). Il messaggio di errore suggerisce che il compilatore non ha visto la tua definizione.

let two = <@ 2 @> 
let oneAndTwo = <@ 1 + %two @> 
Problemi correlati