2016-07-04 23 views
5

मैं एक संग्रह बनाने की कोशिश कर रहा हूं जिसमें कई संभावित प्रकार हैं। यह एक उदाहरण है कि मैं इसे कैसे देखना चाहता हूं:एक विशिष्ट प्रकार कैसे परिवार के प्रकार से संबंधित है?

type Position = Vector2 
type Velocity = Vector2 
type Appearance = String 

type Component = Position | Velocity | Appearance 

let components = List<Dictionary<string, Component>>() 
let pos = Dictionary<string, Position>() 

components.Add(pos) // Type "Position" does not match with type "Component" 

मैं विशिष्ट प्रकारों को घोषित करना चाहता हूं जो अभी भी सामान्य प्रकार के अंतर्गत फिट हैं। क्या कोई तरीका है कि मैं अपना कोड इस तरह लिख सकता हूं? क्या ऐसा करने के लिए एक और बेवकूफ तरीका है?

प्रकार लघुरूप (Link)

type Position = Vector2 
type Velocity = Vector2 
type Appearance = String 

प्रकार संक्षिप्त रूपों सिर्फ एक मौजूदा प्रकार के लिए एक और नाम को परिभाषित, प्रकार पर:

+3

क्या आप समझते हैं कि घटक। स्थिति और स्थिति एक और समान नहीं है? –

उत्तर

6

वहाँ रहे हैं आप यहाँ अपने कोड में है चीजों के एक जोड़े हैं बाएं और दाएं और सटीक समकक्ष और एक दूसरे के लिए इस्तेमाल किया जा सकता है।

इस प्रश्न के अनुरूप एक उदाहरण देने के लिए, F # में मानक .NET List के लिए एक प्रकार का संक्षेप है, इसे ResizeArray कहा जाता है। यह इस तरह से परिभाषित किया है:

type ResizeArray<'T> = System.Collections.Generic.List<'T> 

यह आप इसका इस्तेमाल करने में System.Collections.Generic को खोले और यह एफ # में list प्रकार के साथ भ्रम से बचा जाता है में मदद करता है, लेकिन यह अन्य की तुलना में लिए कोई नया नाम जोड़ने के कुछ नहीं करता बचाता है एक मौजूदा प्रकार

Disciminated यूनियन (Link)

type Component = Position | Velocity | Appearance 

यहाँ आप Component कहा जाता है एक प्रकार है, तो आप तीन कंस्ट्रक्टर्स के साथ एक प्रकार के रूप में यह के बारे में सोच सकते हैं: Position, Velocity और Appearance। आप पैटर्न मिलान से एक ही तीन मामलों का उपयोग करके फिर से प्रकार को डीकस्ट्रक्चर कर सकते हैं।

उदा।

match comp with 
|Position -> .. 
|Velocity -> .. 
|Appearance -> .. 

उम्मीद है, यह अब कोई आश्चर्य की बात है कि प्रकार संक्षिप्त नाम Position कि आप घोषित संघ मामले Position कि आप Component प्रकार के भाग के रूप में घोषित के साथ कोई संबंध नहीं है के रूप में आना चाहिए। वे पूरी तरह से एक दूसरे से स्वतंत्र हैं।

Position का अर्थ है Vector2 और Component एक पूरी तरह से पृथक संघ प्रकार है।

मान लें कि आप Component प्रकार चाहते हैं जिसमें एकाधिक चीज़ें हो सकती हैं, आपको कुछ मूल्यों को मामलों के साथ जोड़ना होगा।

type Component = 
    | Position of Vector2 
    | Velocity of Vector2 
    | Appearance of string 

अब, चलो अगले समस्या को देखो: यहाँ इस तरह के एक साथ भेदभाव संघ बनाने का एक उदाहरण है।

हम प्रकार संक्षिप्त रूपों हटा सकते हैं और हमारे नए भेदभाव संघ

let components = List<Dictionary<string, Component>>() 
let pos = Dictionary<string, Position>() 

साथ कोड के बाकी की कोशिश अब हम एक नई त्रुटि है, तो:

The type Position is not defined.

ठीक है, याद है कि मैं क्या पहले कहा लगभग ComponentComponent प्रकार है, Position एक प्रकार नहीं है, यह Component का यूनियन केस है।

आप इन विकल्पों में से एक ही एक के पूरे शब्दकोशों शामिल करना चाहता था, तो आप इस तरह कुछ करने के लिए अपनी परिभाषा बदल रहा है बेहतर हो सकता है:

type ComponentDictionary = 
    |PositionDictionary of Dictionary<string, Vector2> 
    |VelocityDictionary of Dictionary<string, Vector2> 
    |AppearanceDictionary of Dictionary<string, string> 

तो फिर तुम इनमें से एक ResizeArray/List बना सकते हैं।

let components = ResizeArray<ComponentDictionary>() 

अब, यह संग्रह आबादी के क्रम में, हम तो बस के लिए ComponentDictionary

let pos = PositionDictionary (Dictionary<string, Vector2>()) 

अब उचित मामले निर्माता का उपयोग की जरूरत है, स्थिति, ताकि हम उसे घटकों को जोड़ सकते हैं प्रकार ComponentDictionary की है:

components.Add(pos) // No error here! 
1

TheInnerLight का उत्तर बहुत पूरा है। मैं यह जोड़ना चाहता हूं कि सामान्य .NET सूची और शब्दकोश के बजाय शुद्ध F # प्रकार (सूची, मानचित्र या dict) का उपयोग करने का कुछ लाभ हो सकता है। बेशक आपको वास्तव में .NET जेनेरिक संग्रह की आवश्यकता हो सकती है। यहाँ एक सरल उदाहरण है जो नक्शे (या dict) का उपयोग करता है और विभिन्न घटक नक्शों की सूची बनाता है:

type Vector2 = float * float 

type Component = 
    | Position of Vector2 
    | Velocity of Vector2 
    | Appearance of string 

type Components = list<Map<string,Component>> // this is not strictly necessary 

let pos = Position(10.,20.) 
let app = Appearance "here" 

let compMap1= Map.empty<string,Component> // define an empty map for Component 
let compMap1 = compMap1.Add("key1",pos).Add("key2",app) // or: let compMap1' = dict(["key1",pos;"key2",app]) 
let compMap2 = ["key3",pos;"key4",pos] |> Map.ofList // you can create map from a list 
let (components:Components) = [compMap1;compMap2] // make a list of your maps 
let components' = [compMap1;compMap2] // or just use a generic F# list 
(* 
val components' : Map<string,Component> list = 
    [map [("key1", Position (10.0, 20.0)); ("key2", Appearance "here")]; 
    map [("key3", Position (10.0, 20.0)); ("key4", Position (10.0, 20.0))]] 
*) 

और अगर सिर्फ (या सरणी, या जो कुछ भी) एक सूची की आवश्यकता होगी कि विभिन्न घटक प्रकार रखती है आप पहले से ही कर सकते हैं ऐसा करें:

let compList = [pos;app] 
//val compList : Component list = [Position (10.0, 20.0); Appearance "here"] 
संबंधित मुद्दे