2012-05-06 14 views

Odpowiedz

5

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.

4

Nie jestem dokładnie pewien, dlaczego operator % zachowuje się w ten sposób, ale można przedefiniować go za pomocą globalnej let oprawa:

let (~%) a = -a 
%10 

Jeśli operator nie może być zdefiniowana jako static członka (nie jestem pewien jeśli tak jest, lub jeśli czegoś brakuje), nadal możesz zdefiniować definicję, która wywołuje jakiś statyczny element obiektu. To powinno dać zasadniczo taką samą funkcjonalność:

// 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 

Tło: W F # Kod notowań, jest ona wykorzystywana do „składania” wyrażeń do innego wyrazu (aby zbudować wyrażenie składa się z innego, wcześniej zdefiniowanego wyrażenie). Komunikat o błędzie sugeruje, że kompilator nie widział Twojej definicji.

let two = <@ 2 @> 
let oneAndTwo = <@ 1 + %two @> 
Powiązane problemy