2012-04-10 37 views
6

Để tạo một chuỗi các lớp học của tôi,F # - Tôi có thể sử dụng tên kiểu như một hàm hoạt động như một hàm tạo mặc định không?

type MyInt(i:int) = 
    member this.i = i 

[1;2;3] |> Seq.map(fun x->MyInt(x)) 

nơi fun x->MyInt(x) có vẻ là không cần thiết. Sẽ tốt hơn nếu tôi có thể viết Seq.map(MyInt)

Nhưng tôi không thể. Một giải pháp mà tôi có thể nghĩ đến là xác định một chức năng riêng biệt

let myint x = MyInt(x) 
[1;2;3] |> Seq.map(myint) 

Có cách nào tốt hơn để làm điều này không?

Trả lời

7

Tóm lại, không.

Trình tạo đối tượng không phải là hàm hạng nhất trong F #. Đây là một trong nhiều lý do để không sử dụng các lớp học, phân biệt đối xử công đoàn là tốt hơn để sử dụng ở đây:

type myInt = MyInt of int 
let xs = [1;2;3] |> Seq.map MyInt 

Nếu bạn không thích lambdas rõ ràng, biểu hiện chuỗi trông đẹp hơn trong ví dụ của bạn:

let xs = seq { for x in [1;2;3] -> MyInt x } 

Ngoài , cách giải quyết của bạn là một giải pháp tốt đẹp.

9

Nếu hacks vu vơ không làm phiền bạn, bạn có thể làm:

///functionize constructor taking one arg 
let inline New< ^T, ^U when ^T : (static member ``.ctor`` : ^U -> ^T)> arg = 
    (^T : (static member ``.ctor`` : ^U -> ^T) arg) 

type MyInt(i: int) = 
    member x.i = i 

[0..9] |> List.map New<MyInt, _> 

EDIT: Như kvb chỉ ra, một chữ ký đơn giản hơn (và ít hacky) có thể được sử dụng:

let inline New x = (^t : (new : ^u -> ^t) x) 

Lưu ý, điều này chuyển loại args xung quanh, do đó, nó sẽ trở thành New<_, MyInt>.

+0

Định nghĩa của bạn về 'Mới' không biên dịch cho tôi trong bản Beta VS11. Tuy nhiên, một biến thể đơn giản hơn: 'let inline New x = (^ t: (mới:^u ->^t) x)'. – kvb

+0

Tôi đã thử rằng đầu tiên, nhưng với ràng buộc rõ ràng '^ t khi^t: (mới:^u ->^t)' mà không biên dịch trong VS2010. Vui mừng khi biết có một cách đơn giản hơn để thực hiện việc này. – Daniel

+0

Oddly trình biên dịch chỉ hỗ trợ ràng buộc constructor rõ ràng của biểu mẫu 'new: unit -> 't' (có thể biểu diễn trực tiếp trong .NET metadata), nhưng bạn có thể sử dụng biểu thức _invocation biểu thức ràng buộc chung hơn và cho trình biên dịch suy ra các ràng buộc . Nó chắc chắn là một lỗ hổng trong hệ thống. – kvb

0

Tôi sử dụng các phương pháp tĩnh cho mục đích này. Lý do là đôi khi nhà xây dựng đối tượng của bạn cần hai đối số được lấy từ nhiều nguồn khác nhau, và cách tiếp cận của tôi cho phép bạn sử dụng List.map2:

type NumRange(value, range) = 
    static member Make aValue aRange = new NumRange(aValue, aRange) 

let result1 = List.map2 NumRange.Make values ranges 

ứng dụng một phần không bị cấm cũng như:

let result2 = 
    values 
    |> List.map NumRange.Make 
    |> List.map2 id <| ranges 

Nếu bạn không thích sử dụng id tại đây, bạn có thể sử dụng (fun x y -> x y) dễ đọc hơn.

1

Để cập nhật về điều này - F# 4.0 đã nâng cấp các hàm xây dựng lên các hàm hạng nhất, vì vậy giờ đây chúng có thể được sử dụng ở bất kỳ đâu có thể sử dụng hàm hoặc phương thức.

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