2011-01-11 28 views
7

Sau khi một số chơi xung quanh F trở ngại # thành viên tính năng và chức năng viết như thế này:F trở ngại # thành viên +^a ByRef thông số

let inline parse< ^a when ^a : (static member Parse: string -> ^a) > s = 
    (^a: (static member Parse: string -> ^a) s) 

đó làm việc hoàn toàn tốt đẹp:

let xs = [ "123"; "456"; "999" ] |> List.map parse<int> 

Tôi đang cố gắng để viết khác func tryParse, sử dụng phương pháp tĩnh TryParse và kết thúc kết quả phân tích cú pháp thành loại 'a option để được hỗ trợ tốt hơn trong F #. Một cái gì đó như thế này không biên dịch:

let inline tryParse s = 
    let mutable x = Unchecked.defaultof< ^a> 
    if (^a: (static member TryParse: string * ^a byref -> bool) (s, &x)) 
     then Some x else None 

Lỗi này là:

lỗi FS0001: biểu hiện này được dự kiến ​​sẽ có loại ByRef < 'a> nhưng ở đây đã gõ 'a ref

F # ref-cell d oesn't work too:

let inline tryParse s = 
    let x = ref Unchecked.defaultof< ^a> 
    if (^a: (static member TryParse: string * ^a byref -> bool) (s, x)) 
     then Some x else None 

Tôi đang làm gì sai?

+0

Yikes, tôi nghĩ đây là một lỗi ... cũng, 'TryParse: string -> bool *^a' không hoạt động. –

+0

Điều này dường như được sửa trong F # 3.0. – kvb

Trả lời

4

CẬP NHẬT

này dường như được cố định trong F # 3.0.

Cũ câu trả lời:

Tôi đồng ý với bình luận của Stephen rằng nó rất có thể là một lỗi. Có nhiều hạn chế về các loại byref, do đó, nó không đặc biệt gây ngạc nhiên với tôi rằng chúng không chơi tốt với các ràng buộc của thành viên. Đây là cách giải quyết (xấu xí) bằng cách sử dụng sự phản chiếu:

type parseDel<'a> = delegate of string * 'a byref -> bool 

type Parser< ^a when ^a : (static member TryParse: string * ^a byref -> bool)> private()= 
    static let parser = System.Delegate.CreateDelegate(typeof<parseDel<'a>>, typeof<'a>.GetMethod("TryParse", [|typeof<string>; typeof<'a>.MakeByRefType()|])) :?> parseDel<'a> 
    static member inline ParseDel = parser 

let inline tryParse (s:string) = 
    let mutable x = Unchecked.defaultof< ^a> 
    if Parser<_>.ParseDel.Invoke(s, &x) then 
    Some x 
    else None 

let one : int option = tryParse "1" 
1

Tôi nghĩ rằng đó cũng là lỗi, điều gì đó có ràng buộc thành viên và các loại byref. Tôi có thể làm cho một phiên bản phản ánh một chút ít xấu xí bằng cách thay đổi chữ ký của các hạn chế thành viên:

let inline tryParse<'a when 'a : (static member TryParse : string -> 'a byref -> bool)> s = 
    let args = [| s ; null |] 
    if typeof<'a> 
     .GetMethod("TryParse", [| typeof<string>; typeof< ^a>.MakeByRefType() |]) 
     .Invoke(null, args) = box true 
     then Some (args.[1] :?> 'a) 
     else None 

Cái này là rất gần:

let inline tryParse< ^a when ^a: (static member TryParse: string -> ^a byref -> bool)> s = 
    let mutable x = Unchecked.defaultof<'a> 
    if (^a: (static member TryParse: string -> ^a byref -> bool) (s, &x)) 
     then Some x else None 

nhưng tôi nhận được một lỗi FS0421: Địa chỉ của biến 'x' không thể được sử dụng tại thời điểm này khi tôi cố gắng biên dịch nó.

1

này biên dịch nhưng vẫn không hoạt động như mong đợi:

let inline tryParse< ^a when ^a: (static member TryParse: string -> ^a ref -> bool) > s = 
    let x = ref Unchecked.defaultof< ^a> 
    match (^a: (static member TryParse: string -> ^a ref -> bool) (s, x)) with 
    | false -> None 
    | true -> Some(!x) 

// returns [Some 0; Some 0; Some 0; null], so our tryParse is not retrieving the value from the ref 
let xs = [ "1"; "456"; "999"; "a" ] |> List.map tryParse<int> 

trong trường hợp cụ thể này, thay vì sử dụng phản ánh Tôi chỉ sẽ tái TryParse ra khỏi Parse trong f #

let inline tryParse< ^a when ^a: (static member Parse: string -> ^a) > s = 
    try 
    Some(^a: (static member Parse: string -> ^a) s) 
    with 
    | exn -> None 

let xs = [ "1"; "456"; "999"; "a" ] |> List.map tryParse<int> 
+0

Tôi đã nêu điều này lên [email protected] –

Các vấn đề liên quan