2012-05-06 20 views

Trả lời

5

Lý do tại sao bạn đang nhìn thấy hành vi này là bởi vì F # không định nghĩa (~%) với các ràng buộc tĩnh giống như hầu hết các nhà khai thác cấp cao nhất. Nó được định nghĩa là hàm Quotations.Expr<'a> -> 'a. Do đó, hàm (~%) (là bí danh cho op_Splice) bạn đã xác định trên loại T không được giải quyết bằng cách sử dụng toán tử (~%) cấp cao nhất.

Bạn có thể thấy điều này bởi sự tương tác FSI sau:

> <@ (~%) @>;; 

    <@ (~%) @>;; 
    ^^^^^^^^^^ 

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. 

Vì vậy, nếu chúng ta xác định lại cấp cao nhất (~%) điều hành như sau, sau đó dụ của bạn sẽ biên dịch mà không có lỗi:

let inline (~%) (x : ^a) = (^a : (static member op_Splice : ^a -> 'b) (x)) 

nhưng lưu ý rằng việc trích dẫn báo giá sẽ không còn hoạt động:

let x = <@ 3 @> 
<@ %x @> 
----^ 
error FS0001: The type 'Expr<int>' does not support the operator '~%' 

đó là bởi vì định nghĩa ban đầu của (~%) được xử lý đặc biệt bởi trình biên dịch để nối báo giá. Thật vậy, bạn có thể see trong các chữ ký ExprExpr<'T> rằng các loại đó không xác định bất kỳ toán tử nào cả, hãy để một mình op_Splice.

Bạn có thể xem các kết quả tương tự với các toán tử mã hóa &&||. Có thể được định nghĩa lại (ánh xạ tới op_BooleanAndop_BooleanOr), nhưng trừ khi chúng là, chúng được xử lý đặc biệt bởi trình biên dịch.

4

Tôi không chắc chắn chính xác lý do tại sao các nhà điều hành % cư xử như thế này, nhưng bạn có thể định nghĩa lại nó bằng cách sử toàn cầu let ràng buộc:

let (~%) a = -a 
%10 

Nếu các nhà điều hành không thể được định nghĩa là static thành viên (tôi không chắc chắn nếu đó là trường hợp, hoặc nếu tôi chỉ thiếu một cái gì đó), bạn vẫn có thể xác định một định nghĩa inline mà gọi một số thành viên tĩnh của một đối tượng. Điều này sẽ cung cấp cho bạn cơ bản là chức năng tương tự:

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

Bối cảnh: Trong F # mã kép, nó được sử dụng cho "nối" các biểu thức vào biểu khác (để xây dựng một biểu thức bao gồm từ khác, được định nghĩa trước biểu hiện). Thông báo lỗi cho thấy trình biên dịch không thấy định nghĩa của bạn.

let two = <@ 2 @> 
let oneAndTwo = <@ 1 + %two @> 
Các vấn đề liên quan