2012-11-26 28 views
5

Xin chào, tất cả!Có cách nào an toàn để chuyển đổi Bộ sưu tập thành chuỗi trong F # không?

Vì vậy, tôi đã chơi xung quanh với các cách để đưa Bộ sưu tập .NET vào cấu trúc dữ liệu chức năng. Điều tốt nhất tôi có thể làm là đưa nó vào một seq đầu tiên và bất cứ điều gì tôi muốn sau đó.

Vấn đề là điều này dường như phá vỡ suy luận kiểu, rõ ràng là không an toàn.

Ví dụ:

let a = new System.DirectoryServices.DirectorySearcher("<query>") in 
let entries = a.FindAll() 
let entries_list = 
    let (entries_seq : seq<obj>) = Seq.cast entries_list in 
    Seq.toList entries_Seq 
in 
entries_list (* list of AD objects found from query, has type obj *) 

Để làm được bất cứ điều gì hữu ích với entries_list, tôi sẽ phải làm:

entries_list :?> SearchResult 

Đang cố gắng để khái quát nó vào một seq < 'a> thất bại, kể từ trình biên dịch vẫn yêu cầu tôi gõ kiểu tĩnh của nó (điều này có ý nghĩa).

Có cách nào để tránh điều này không? Tôi bắt đầu nghĩ rằng đây là một hạn chế của việc sử dụng các cấu trúc dữ liệu .NET theo cách chức năng.

Xin lỗi nếu đây là câu hỏi mới; Tôi là màu xanh lá cây để F # và lập trình chức năng nói chung (và đang yêu nó!). Chúc mừng!

  • Carlos.
+0

Không thực hiện 'let entries_seq: seq <_> ...'công việc - điều này sẽ cung cấp cho một chuỗi đánh máy mạnh mẽ –

+0

Nó không; Tôi nhận được lỗi giới hạn giá trị, phù hợp với những gì tôi đã thấy trước đây. –

Trả lời

11

Như Daniel nói, bạn thường nên không cần phải sử dụng Seq.cast bởi vì hầu hết các bộ sưu tập sẽ đã thực hiện các giao diện chung seq<'t>. Tuy nhiên, có một số loại bộ sưu tập .NET được xây dựng trước khi giới thiệu Generics trong .NET 2.0 chỉ triển khai giao diện không chung chung IEnumerable. Trình biên dịch F # thực sự có một số logic đặc biệt trong các vòng lặp for được gọi là "khai thác được liệt kê" để làm việc chống lại các loại bộ sưu tập này dễ dàng hơn một chút. Do đó, nếu bạn chỉ làm việc với một trong các loại bộ sưu tập (ví dụ bạn đang làm việc với DirectoryServices.SearchResultCollections rất nhiều), sau đó nó có thể làm cho tinh thần để chỉ đơn giản là tạo một hàm helper đơn giản:

let typedSearchResults (s:SearchResultCollection) = 
    seq { for result in s -> result } 

mà bạn có thể sau đó sử dụng thay vì Seq.cast cho loại bộ sưu tập cụ thể này.

Nếu bạn đang sử dụng rất nhiều bộ sưu tập kiểu cũ khác nhau trong cùng một dự án, sau đó bạn có thể sử dụng một số F # tính năng ưa thích để làm cho một generic Seq.cast thay thế:

module Seq = 
    let inline inferCast s = 
     // constrain ^t to have an Item indexed property (which we don't actually invoke) 
     let _ = fun x -> (^t : (member Item : int -> ^v with get) (x, 0)) 
     let e = (^t : (member GetEnumerator : unit -> ^e) s) 
     seq { while (^e : (member MoveNext : unit -> bool) e) do 
       yield (^e : (member Current : obj) e) :?> ^v } 

Bây giờ bạn có thể sử dụng Seq.inferCast thay vì Seq.cast và loại mục chính xác sẽ được phỏng đoán cho bạn. Đây có lẽ là quá mức cần thiết trong trường hợp của bạn.

+1

+1 Nice trick, nhưng bạn quên 'inline'. – Daniel

+0

@Daniel - cảm ơn, đã sửa. – kvb

+0

Đó thực sự có thể là chính xác những gì tôi đang tìm kiếm. Cảm ơn rất nhiều! –

3

bộ sưu tập Hầu hết .NET thực hiện IEnumerable<T> (bí danh như seq<'T> trong F #) nhưng thỉnh thoảng bạn sẽ chạy trên một mà chỉ thực hiện các giao diện phi generic IEnumerable. SearchResultCollection là một loại như vậy. Bạn có thể sử dụng Seq.cast để chuyển đổi các bộ sưu tập đó thành seq<'T>, có thể sử dụng chúng với các hàm trong mô-đun Seq.

open System.DirectoryServices 

use searcher = new DirectorySearcher("<query>") 
let entries = searcher.FindAll() |> Seq.cast<SearchResult> 
let entries_list = Seq.toList entries 
+0

Cảm ơn bạn đã phản hồi nhanh! Tôi nhận được nhiều điều đó, nhưng làm cách nào để khái quát hóa điều này cho tất cả các bộ sưu tập như vậy? Có vẻ như tôi không thể làm được nhiều việc gõ tĩnh. Carlos –

+0

Bạn có muốn 'Seq.cast' nhưng không yêu cầu loại arg? Vâng, trong nhiều trường hợp nó có thể được suy ra từ việc sử dụng sau này của trình tự. kvb đã đưa ra một giải pháp thú vị, nhưng thậm chí nó có một số hạn chế. – Daniel

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