2016-06-28 6 views
6

मुझे उम्मीद है कि मेरे डीयू को अपेक्षित काम करने में समस्या हो रही है। मैं एक नया ड्यू जो या तो मैं नहीं समझ सकता क्यों यह मुझे एक "त्रुटि" बनाने की अनुमति है, तो प्रकार < 'एक> या किसी अपवाद System.Exceptionएफ # भेदभाव संघ प्रकार का अंक

से
open System 

// New exceptions. 
type MyException(msg : string) = inherit Exception(msg) 
type MyOtherException(msg : string) = inherit MyException(msg) 

// DU to store result or an exception. 
type TryResult<'a, 't> = 
    | Result of 'a 
    | Error of 't :> Exception 

//This is fine. 
let result = Result "Test" 

// This works, doing it in 2 steps 
let ex = new MyOtherException("Some Error") 
let result2 = Error ex 

// This doesn't work. Gives "Value Restriction" error. 
let result3 = Error (new MyOtherException("Some Error")) 

व्युत्पन्न का एक परिणाम है परिभाषित किया है मैं इसे 2 चरणों में करता हूं, लेकिन जब मैं एक ही पंक्ति पर एक ही चीज कर रहा हूं, तो मुझे वैल्यू प्रतिबंध त्रुटि मिलती है।

मुझे क्या याद आ रही है?

धन्यवाद

अद्यतन

, @kvb द्वारा पोस्ट को देखते हुए प्रकार की जानकारी हर बार मैं एक त्रुटि थोड़ा वर्बोज़ लग रहा था बनाने की जरूरत को जोड़ने, तो मैं इसे लिपटे एक अतिरिक्त विधि में जो एक त्रुटि बनाता है और थोड़ा और संक्षिप्त है।

// New function to return a Result 
let asResult res : TryResult<_,Exception> = Result res 

// New function to return an Error 
let asError (err : Exception) : TryResult<unit,_> = Error(err) 

// This works (as before) 
let myResult = Result 100 

// This also is fine.. 
let myResult2 = asResult 100 

// Using 'asError' now works and doesn't require any explicit type information here. 
let myError = asError (new MyException("Some Error")) 

मुझे यकीन नहीं है कि 'इकाई' के साथ एक त्रुटि निर्दिष्ट करने से कोई परिणाम नहीं होगा जो मैंने अभी तक नहीं देखा है।

TryResult<unit,_> = Error(err) 

उत्तर

5

इस मामूली बदलाव पर विचार करें:

type MyOtherException(msg : string) = 
    inherit MyException(msg) 
    do printfn "%s" msg 

let ex = new MyOtherException("Some Error") // clearly, side effect occurs here 
let result2 = Error ex // no side effect here, but generalized value 

let intResults = [Result 1; result2] 
let stringResults = [Result "one"; result2] // can use result2 at either type, since it's a generalized value 

let result3 = Error (MyOtherException("Some Error")) // result would be of type TryResult<'a, MyOtherException> for any 'a 

// In some other module in a different compilation unit 
let intResults2 = [Result 1; result3]  // why would side effect happen here? just using a generic value... 
let stringResults2 = [Result "one"; result3] // likewise here... 

मुद्दा यह है कि यह लग रहा है result3 की तरह एक मूल्य है, लेकिन नेट प्रकार प्रणाली सामान्य मूल्यों का समर्थन नहीं करता, यह केवल ठोस प्रकार के मूल्यों का समर्थन करता है। इसलिए, MyOtherException कन्स्ट्रक्टर को हर बार result3 का उपयोग करने की आवश्यकता होती है; हालांकि, इसके परिणामस्वरूप किसी भी दुष्प्रभाव का एक से अधिक बार हो रहा है, जो आश्चर्यजनक होगा।Ringil पता चलता है, तुम वैसे भी एक मूल्य के रूप में अभिव्यक्ति के इलाज के लिए संकलक बताकर इस पर काम कर सकते हैं:

[<GeneralizableValue>] 
let result3<'a> : TryResult<'a,_> = Error(new MyOtherException("Some Error")) 

यह रूप में लंबे समय के रूप में निर्माता साइड इफेक्ट नहीं है ठीक है।

+0

धन्यवाद। यह समझ में आता है। मैंने अपना प्रश्न अपडेट किया है जिसमें अतिरिक्त त्रुटि निर्माण विधि शामिल है जो ठीक काम करने लगती है और इसे थोड़ा सा रखती है। केवल सवाल यह है कि इस प्रकार को अब TryResult के रूप में निर्दिष्ट किया गया है, यह सुनिश्चित नहीं है कि इसमें कोई डाउन-साइड होगा या नहीं। – Moog

2

आप कर सकते हैं:

let result3<'a> = Error (new MyOtherException("Some Error")) 

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

क्यों आप इसे एक कदम में ऐसा नहीं कर सकते, पहले ध्यान दें कि यह वही त्रुटि में परिणाम के लिए के रूप में:

let result4 = Result (new MyOtherException("Some Error")) 

जैसा यह करता है:

let result4 = Result ([|1;|]) 

लेकिन यह काम करता है कि:

let result4 = Result ([1;]) 

क्या अपवाद और सरणी के बारे में इसी तरह की है, लेकिन नहीं सूचियाँ? यह उनकी उत्परिवर्तन है। मूल्य प्रतिबंध आपको परेशान करेगा जब आप एक चरण में एक प्रकार के साथ TryResult बनाने की कोशिश करते हैं जो एक ही चरण में परिवर्तनीय है।

अब क्यों दो चरणों की प्रक्रिया हल करती है, ऐसा इसलिए है क्योंकि कन्स्ट्रक्टर पूरे कार्य को सामान्यीकृत नहीं करता क्योंकि आप निर्माता को फ़ंक्शन लागू कर रहे हैं। लेकिन इसे दो चरणों में विभाजित करना हल करता है। यह केस 2 here on MSDN के समान है।

आप उपरोक्त एमएसडीएन आलेख में इसके बारे में अधिक पढ़ सकते हैं और यह this more indepth blog post में क्यों होता है।

+0

ठीक है, धन्यवाद। यह एक काम है। कोई विचार यह है कि इसे 2 चरणों में करने के दौरान इस अतिरिक्त पैरामीटर की आवश्यकता क्यों नहीं है? – Moog

+0

मैंने कुछ स्पष्टीकरण जोड़ा। – Ringil

+4

यह नहीं है कि सरणी उत्परिवर्तनीय हैं लेकिन सूचियां नहीं हैं - यह "सामान्यीकृत अभिव्यक्ति" के बारे में क्या है। उदाहरण के लिए, देखें कि यदि आप 'परिणाम ([1] @ [2])' या 'परिणाम [| |] '। इसके अलावा, आपका कामकाज मेरे लिए बहुत अच्छा प्रतीत नहीं होता है; परिणामी प्रकार हस्ताक्षर 'वैल परिणाम 3 <'a> है: TryResult ', जो वांछित के रूप में सामान्य नहीं है; यदि आप इस मार्ग पर जाते हैं तो आपको एक प्रकार की एनोटेशन जोड़नी चाहिए। – kvb

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