2016-04-08 8 views
5

एक अवलोकन (चकित मुझे उस तरह) का एक न्यूनतम उदाहरण के बाद:आंशिक विखंडन (एफ #)

type Vector = V of float*float 

// complete unfolding of type is OK 
let projX (V (a,_)) = a 

// also works 
let projX' x = 
    match x with 
    | V (a, _) -> a 

// BUT: 
// partial unfolding is not Ok 
let projX'' (V x) = fst x 

// consequently also doesn't work 
let projX''' x = 
    match x with 
    | V y -> fst y 

कारण यह है कि एक आंशिक रूप से deconstructed प्रकार के खिलाफ मैच के लिए यह असंभव बना देता है क्या है?

कुछ आंशिक deconstructions ठीक होने लगते हैं:

// Works 
let f (x,y) = fst y 

संपादित करें: ठीक है, मैं अब (अपने जवाब & टिप्पणी के लिए धन्यवाद) व्यवहार वर्णित की "तकनीकी" कारण समझते हैं। हालांकि, मुझे लगता है कि भाषा के अनुसार, इस व्यवहार को शेष भाषा की तुलना में थोड़ा "अप्राकृतिक" लगता है:

"बीजगणितीय", मेरे लिए, यह प्रकार से "टी" प्रकार को अलग करने के लिए अजीब लगता है "(टी) "। ब्रैकेट्स (इस संदर्भ में) उदाहरण के लिए उदाहरण देने के लिए उपयोग किया जाता है जैसे उदा। में "(टी * एस) * आर" बनाम "टी * (एस * आर)"। इसके अलावा FSI जवाब तदनुसार, कि क्या मैं

type Vector = (int * int) 

या

type Vector = int * int 

भेज FSI के लिए, इस सवाल का जवाब हमेशा होता है

प्रकार वेक्टर = int * पूर्णांक

को देखते हुए उन अवलोकन, एक निष्कर्ष निकाला है कि "int * int" और "(int * int)" बिल्कुल वही प्रकार और टी दर्शाता है hus कि कोड के किसी भी हिस्से में एक की सभी घटनाओं को दूसरे के साथ बदल दिया जा सकता है (रेफरी। पारदर्शिता) ... जैसा कि हमने देखा है वह सच नहीं है।

आगे यह महत्वपूर्ण लगता है कि हाथ में व्यवहार की व्याख्या करने के लिए, हमें भाषा के अर्थपूर्ण गुणों के बजाय "कुछ कोड कैसे संकलन के बाद दिखता है" के बारे में बात करना पड़ा, जो इमो इंगित करता है कि कुछ " भाषा अर्थशास्त्र के बीच तनाव "एक संकलक वास्तव में क्या करता है।

+1

कंपाइलर सामग्री के लिए वास्तविक ट्यूपल का उपयोग करने के लिए इसे 'प्रकार वेक्टर = वी (फ्लोट * फ्लोट)' के साथ आज़माएं। – kvb

+0

यह काम करता है! ... लेकिन यह कैसे अंतर कर सकता है ... मेरा मतलब है प्रकार वेक्टर = (फ्लोट का वी) * फ्लोट वैध भी नहीं होगा? –

+1

सवाल यह है: क्या x * y' का मतलब है "वी प्रकार x और y के प्रकारों का एक टुपल रखता है" या "वी के प्रकार के दो अलग-अलग फ़ील्ड x और y" हैं? यदि आप ट्यूपल को संश्लेषित नहीं करते हैं तो संकलक बाद वाले को मानता है, लेकिन यदि आप इसे संश्लेषित करते हैं, तो इसका मतलब है पूर्व। यह भेद मुख्य रूप से अन्य .NET भाषाओं के साथ इंटरऑप के लिए महत्वपूर्ण है, लेकिन जैसा कि आपने पाया है कि यह कुछ परिस्थितियों में F # के भीतर इस प्रकार के मानों के साथ कैसे बातचीत करता है, यह भी प्रभावित कर सकता है। आपकी टिप्पणी के लिए – kvb

उत्तर

1

एफ # में

type Vector = V of float*float 

सिर्फ एक degenerated संघ है (जैसा कि आप देख सकते हैं कि दृश्य स्टूडियो में यह माउस ले जाकर), तो यह करने के लिए बराबर है:

type Vector = 
    | V of float*float 

of के बाद भाग दो anonymous field बनाता है एस (जैसा कि एफ # संदर्भ में वर्णित है) और प्रकार के फ्लोट के दो पैरामीटर स्वीकार करने वाला एक कन्स्ट्रक्टर।

यदि आप को परिभाषित

type Vector2 = 
    | V2 of (float*float) 

केवल एक गुमनाम क्षेत्र है जो तैरता के एक टपल और एक एकल पैरामीटर के साथ एक निर्माता है। जैसा कि टिप्पणी में बताया गया था, वांछित पैटर्न मिलान करने के लिए आप Vector2 का उपयोग कर सकते हैं।

कि आखिरकार, यह विसंगत लग सकता है कि निम्नलिखित कोड काम करता है:

let argsTuple = (1., 1.) 
let v1 = V argsTuple 

हालांकि, अगर आप वहाँ एक छिपे हुए पैटर्न मिलान है कि ध्यान में रखना, सब कुछ स्पष्ट किया जाना चाहिए।

संपादित करें:

F# language spec (p 122) राज्यों स्पष्ट रूप से संघ परिभाषा में है कि कोष्ठक बात:

कोष्ठक संघ परिभाषा में महत्वपूर्ण हैं। इस प्रकार, निम्नलिखित दो परिभाषाएं अलग:

type CType = C of int * int

type CType = C of (int * int)

पहला उदाहरण में कोष्ठकों की कमी का संकेत है कि संघ मामला दो तर्क लेता है। दूसरे उदाहरण में कोष्ठक इंगित करता है कि यूनियन केस एक तर्क लेता है जो प्रथम श्रेणी के ट्यूपल मान है।

मुझे लगता है कि इस तरह के व्यवहार तथ्य यह है कि आप जैसे, एक संघ की परिभाषा को और अधिक जटिल पैटर्न को परिभाषित कर सकते के साथ संगत है:

type Move = 
     | M of (int * int) * (int * int) 

कई तर्क के साथ संघ उपयोग करने में सक्षम होने के नाते भी बहुत बनाता है भावना, खासकर इंटरऑप स्थिति में, जब टुपल्स का उपयोग बोझिल होता है।

दूसरी बात यह है कि आप प्रयोग किया है:

type Vector = int * int 

एक type abbreviation जो केवल एक खास प्रकार के लिए एक नाम देता है। int * int के आसपास कोष्ठक रखने से कोई फर्क नहीं पड़ता क्योंकि उन कोष्ठक को समूहीकरण समूह के रूप में माना जाएगा।

+0

मैं (समझता हूं और) जो कुछ भी कहता हूं उससे सहमत हूं और मैं उस उत्तर को स्वीकार करूंगा। हालांकि, मुझे अभी भी लगता है कि डिजाइन परिभाषा यूनियन परिभाषाओं में कोष्ठक की भूमिका स्वच्छ/सुरुचिपूर्ण पक्ष की बजाय व्यावहारिक पर अधिक है;)। संघ परिभाषाएं हो सकती हैं जहां कुछ कोष्ठक समूहबद्ध करने के लिए होते हैं जबकि अन्यों के बारे में पहले चर्चा की जाती है ... "... = एक्स का एक्स" फ़ॉर्म की और परिभाषा न केवल वाई "एक प्रकार के रूप में" पर निर्भर करती है ... –

+0

मैं मानता हूं कि यह वाक्यविन्यास के मामले में सबसे सहज और साफ डिजाइन विकल्प नहीं है; दूसरी तरफ यह बदसूरत है। –

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