2012-11-26 26 views
5

शुभ दोपहर, सब!क्या F # में अनुक्रम में संग्रह को परिवर्तित करने का कोई सुरक्षित तरीका है?

तो मैं एक कार्यात्मक डेटा संरचना में .NET संग्रह कास्टिंग करने के तरीकों के साथ खेल रहा हूं। सबसे अच्छा मैं प्राप्त करने में सक्षम हूं इसे पहले एक सीक में डालना है और उसके बाद जो भी मैं चाहता हूं।

समस्या यह है कि ऐसा लगता है कि यह ब्रेक प्रकार अनुमान है, जो स्पष्ट रूप से असुरक्षित है।

उदाहरण:

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 *) 

आदेश कुछ भी entries_list के साथ उपयोगी करने के लिए, मुझे क्या करना होगा:,

entries_list :?> SearchResult 

एक seq < 'एक> विफल रहता है के लिए यह सामान्यीकरण करने के लिए कोशिश कर रहा है के बाद से कंपाइलर को अभी भी आवश्यकता है कि मैं स्थिर रूप से इसके गणक टाइप करें (जो समझ में आता है)।

क्या इससे बचने का कोई तरीका है? मुझे लगता है कि यह एक कार्यात्मक तरीके से .NET डेटा संरचनाओं का उपयोग करने की एक सीमा है।

क्षमा करें अगर यह एक नौसिखिया प्रश्न है; मैं सामान्य रूप से एफ # और कार्यात्मक प्रोग्रामिंग के लिए हरा हूं (और इसे प्यार कर रहा हूँ!)। चीयर्स!

  • कार्लोस।
+0

'प्रविष्टियों_seq: seq <_> कर रहा है ...'काम - यह दृढ़ता से टाइप किया गया अनुक्रम –

+0

देना चाहिए; मुझे एक मूल्य प्रतिबंध त्रुटि मिलती है, जो कि मैं पहले जो देख रहा था उसके अनुरूप है। –

उत्तर

11

डैनियल कहते हैं, आप आमतौर पर Seq.cast उपयोग करने के लिए है क्योंकि ज्यादातर संग्रह पहले से ही सामान्य seq<'t> इंटरफ़ेस को लागू करेगा की जरूरत नहीं होनी चाहिए। हालांकि, कई .NET संग्रह प्रकार हैं जो .NET 2.0 में जेनेरिक के परिचय से पहले बनाए गए थे जो केवल गैर-जेनेरिक IEnumerable इंटरफ़ेस को लागू करते हैं। एफ # कंपाइलर में वास्तव में for लूप्स में कुछ विशेष तर्क हैं जिन्हें इन प्रकार के संग्रहों के खिलाफ काम करने के लिए "गणना करने योग्य निष्कर्षण" कहा जाता है। इसलिए, यदि आप केवल इन संग्रह प्रकारों में से एक (उदाहरण के लिए आप DirectoryServices.SearchResultCollections बहुत से काम कर रहे हैं) के साथ काम कर रहे हैं, तो यह शायद समझ में बस एक साधारण सहायक समारोह बनाने के लिए बनाता है:

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

है जिसे आप कर सकते हैं इस विशेष संग्रह प्रकार के लिए Seq.cast के बजाय उपयोग करें।

आप एक ही परियोजना में विभिन्न पुरानी शैली संग्रह के बहुत सारे का उपयोग कर रहे हैं, तो आप कुछ फैंसी एफ # सुविधाओं एक सामान्य Seq.cast विकल्प बनाने के लिए उपयोग कर सकते हैं:

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 } 

अब आप Seq.inferCast के बजाय का उपयोग कर सकते Seq.cast, और सही आइटम प्रकार आपके लिए अनुमानित किया जाएगा। हालांकि, यह शायद आपके मामले में अधिक है।

+1

+1 अच्छी चाल है, लेकिन आप 'इनलाइन' भूल गए हैं। – Daniel

+0

@ डैनियल - धन्यवाद, तय। – kvb

+0

वास्तव में वह वही हो सकता है जो मैं ढूंढ रहा हूं। आपका बहुत बहुत धन्यवाद! –

3

अधिकांश नेट संग्रह IEnumerable<T> (एफ # में seq<'T> के रूप में एलियास) को लागू लेकिन कभी कभी आप एक है कि केवल गैर सामान्य इंटरफ़ेस IEnumerable लागू करता है के पार चला जाएगा। SearchResultCollection एक ऐसा प्रकार है। आप पर उन संग्रहों को परिवर्तित करने के लिए Seq.cast का उपयोग कर सकते हैं, जिससे Seq मॉड्यूल में उन्हें फ़ंक्शंस के साथ उपयोग करना संभव हो जाता है।

open System.DirectoryServices 

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

त्वरित प्रतिक्रिया के लिए धन्यवाद! मुझे इतना मिलता है, लेकिन मैं इस तरह के सभी संग्रहों के लिए इसे कैसे सामान्यीकृत करूं? ऐसा लगता है कि मैं बहुत से स्थिर टाइपिंग के बिना नहीं कर सकता। कार्लोस –

+0

क्या आप 'Seq.cast' चाहते हैं लेकिन बिना तर्क के आवश्यकता के? खैर, कई मामलों में इसे अनुक्रम के बाद के उपयोग से अनुमानित किया जा सकता है। केवीबी ने एक दिलचस्प समाधान दिया, लेकिन यहां तक ​​कि इसमें कुछ प्रतिबंध भी हैं। – Daniel

संबंधित मुद्दे

 संबंधित मुद्दे