2013-02-07 46 views
6

स्काला 2.9.1 का उपयोग करना, Either के निम्नलिखित दो उदाहरणों पर विचार करें:स्कैला का कोई भी क्यों नहीं है। राइटप्रोजेक्शन # फ़िल्टर किसी और को वापस लौटाता है?

scala> val er: Either[String, Int] = Right(1) 
er: Either[String,Int] = Right(1) 

scala> val el: Either[String, Int] = Left("a") 
el: Either[String,Int] = Left(a) 

यह बहुत अच्छा है कि, left और right अनुमानों का उपयोग करके, एक के लिए-comprehensions (अनुमानित या तो की पक्षपाती इकाई के माध्यम से) का उपयोग कर सकते है :

scala> for { r <- er.right } yield r * 2 
res6: Product with Either[String,Int] with Serializable = Right(2) 

scala> for { r <- el.right } yield r * 2 
res7: Product with Either[String,Int] with Serializable = Left(a) 

कोई क्यों निर्णय filter विधि एक या तो वापसी के लिए नहीं बनाया गया था मुझे समझा सकते हैं? मैं काम करने के लिए निम्नलिखित की उम्मीद करेंगे है :: 9: त्रुटि:

scala> for { r <- er.right if r > 2 } yield r * 2 // r is NOT greater than 2! 
res8: Product with Either[String,Int] with Serializable = Left(a) 

इसके बजाय आपको निम्न त्रुटि प्राप्त मूल्य * दोनों में [कुछ भी नहीं है, इंट] के लिए {r < सदस्य नहीं है - एर।

scala> er.right.filter(_ > 2) 
res9: Option[Either[Nothing,Int]] = None 

इस में लिए-व्यापक यदि खंड के उपयोग धरा: सही है, तो आर> 2} उपज आर * 2

ऐसा प्रतीत होता है Either.RightProjection#filter में अंतर्निहित कॉल वास्तव में एक Option देता है कि मुर्गी, कम से कम जिस तरह से मैं इसका उपयोग करने की कोशिश कर रहा था।

क्या किसी के पास यह स्पष्टीकरण है कि यह डिज़ाइन ऐसा क्यों है?

उत्तर

11

यह इस तथ्य को उबालता है कि यदि आपके पास Right(b) है, लेकिन आपका फ़िल्टर अनुमान विफल रहता है, तो आपके पास Left डालने का कोई मूल्य नहीं है।

Left("") के डिफ़ॉल्ट मान के साथ विफल होने पर, आप Either[String, Int] के मामले के लिए एक कार्यान्वयन की कल्पना कर सकते हैं। स्कैला मानक पुस्तकालय में आपके लिए मूल्य बनाने की सुविधा नहीं है, क्योंकि इसमें एक अवधारणा शामिल नहीं है जैसे एक मोनॉयड जो एक प्रकार के लिए "खाली" मान निर्धारित करेगा।

scala> \/.right[String, Int](1).filter(_ > 2) 
res1: scalaz.\/[String,Int] = -\/() 
:

Scalaz पुस्तकालय एक monoid typeclass शामिल नहीं है, और संस्करण 7 भी एक सही पक्षपाती अलगाव प्रकार, \/[A, B] (Either[A, B] isomorphic को) जो बाईं प्रकार iff एक filter विधि है शामिल एक monoid है

लेकिन आप सामान्य मामले के लिए ऐसा नहीं कर सके - अगर आपके पास Either[Nothing, Int] था, तो आप कभी भी बाएं मान का उत्पादन नहीं कर सके।

+1

क्या एक अच्छा जवाब है, जो कुल समझ में आता है। क्या इसका मतलब है कि मुझे कुछ ऐसा करना चाहिए: {r <- er.right.filter (_> 2) .toRight ("a") के लिए। JoinRight.right} उपज आर * 2 –

+1

आप पैटर्न पैटर्न पसंद कर सकते हैं: er मैच {केस राइट (बी) यदि बी> 2 => राइट (बी * 2); मामला _ => बाएं ("ए")} ' –