scala सिंटेक्स के लिए "स्कला" के साथ आयर्स का उपयोग करना




monads typeclass (3)

2.12 स्कला के रूप में, Either अब सही पक्षपाती है

documentation :

जैसा कि या तो तरीकों के नक्शे और फ्लैट मैप को परिभाषित करता है, इसका उपयोग समझ के लिए भी किया जा सकता है:

val right1: Right[Double, Int] = Right(1)
val right2                     = Right(2)
val right3                     = Right(3)
val left23: Left[Double, Int]  = Left(23.0)
val left42                     = Left(42.0)

for (
  a <- right1;
  b <- right2;
  c <- right3
) yield a + b + c // Right(6)

for (
  a <- right1;
  b <- right2;
  c <- left23
) yield a + b + c // Left(23.0)

for (
  a <- right1;
  b <- left23;
  c <- right2
) yield a + b + c // Left(23.0)

// It is advisable to provide the type of the “missing” value (especially the right value for `Left`)
// as otherwise that type might be infered as `Nothing` without context:
for (
  a <- left23;
  b <- right1;
  c <- left42  // type at this position: Either[Double, Nothing]
) yield a + b + c
//            ^
// error: ambiguous reference to overloaded definition,
// both method + in class Int of type (x: Char)Int
// and  method + in class Int of type (x: Byte)Int
// match argument types (Nothing)

जैसा कि मैं इसे समझता हूं, "सिंटैक्स के लिए स्काला" हास्केल के मोनडिक "डू" सिंटैक्स के समान है। स्काला में, "के लिए" सिंटैक्स का उपयोग अक्सर List एस और Option एस के लिए किया जाता है। मैं इसे Either एस के साथ उपयोग करना चाहता हूं, लेकिन डिफ़ॉल्ट आयात में आवश्यक तरीके मौजूद नहीं हैं।

for {
  foo <- Right(1)
  bar <- Left("nope")
} yield (foo + bar)

// expected result: Left("nope")
// instead I get "error: value flatMap is not a member..."

क्या यह कार्यक्षमता कुछ आयात के माध्यम से उपलब्ध है?

थोड़ी अड़चन है:

for {
  foo <- Right(1)
  if foo > 3
} yield foo
// expected result: Left(???)

एक सूची के लिए, यह List()Option , यह None होगा। क्या स्काला मानक पुस्तकालय इसका समाधान प्रदान करते हैं? (या शायद scalaz ?) कैसे? मान लीजिए कि मैं अपने स्वयं के "मोनड उदाहरण" प्रदान करना चाहता था, तो मैं यह कैसे कर सकता था?


यह 2.11 और इससे पहले के स्कैला में काम नहीं करता है क्योंकि Either एक सनक नहीं है। हालाँकि इसे सही- LeftProject करने की बात की जा रही है, आप इसका उपयोग समझ में नहीं कर सकते हैं: आपको नीचे की तरह LeftProject या RightProjection प्राप्त करना LeftProject :

for {
  foo <- Right[String,Int](1).right
  bar <- Left[String,Int]("nope").right
} yield (foo + bar)

वह Left("nope") लौटता है, वैसे।

स्कैलाज़ पर, आप Either Validation साथ प्रतिस्थापित करेंगे। मजेदार तथ्य: Either मूल लेखक टोनी मॉरिस हैं, जो कि स्कलाज़ के लेखकों में से एक हैं। वह Either सही-पक्षपाती बनाना चाहता था, लेकिन एक सहयोगी द्वारा अन्यथा आश्वस्त था।


क्या यह कार्यक्षमता कुछ आयात के माध्यम से उपलब्ध है?

हां, लेकिन तीसरे पक्ष के आयात के माध्यम से: स्कलाज़ Either एक मोनाड उदाहरण प्रदान करता है।

import scalaz._, Scalaz._

scala> for {
     |   foo <- 1.right[String]
     |   bar <- "nope".left[Int]
     | } yield (foo.toString + bar)
res39: Either[String,java.lang.String] = Left(nope)

अब if -गार्ड मोनैडिक ऑपरेशन नहीं है। इसलिए अगर आप if guard का उपयोग करने का प्रयास करते हैं, तो यह एक कंपाइलर त्रुटि के परिणामस्वरूप होता है।

scala> for {
     |   foo <- 1.right[String]
     |   if foo > 3
     | } yield foo
<console>:18: error: value withFilter is not a member of Either[String,Int]
                foo <- 1.right[String]
                              ^

ऊपर इस्तेमाल की जाने वाली सुविधा विधियाँ - .right और .left - भी स्कैलाज़ से हैं।

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

मुझे आपका यह सवाल याद आ गया।

मान लीजिए कि मैं अपने स्वयं के "मोनड उदाहरण" प्रदान करना चाहता था, तो मैं यह कैसे कर सकता था?

समझ के for स्काला को केवल .flatMap , .withFilter , और .filter .foreach कॉल्स में शामिल वस्तुओं पर .foreach किया जाता है। (आप पूर्ण अनुवाद योजना here पा सकते हैं।) इसलिए यदि कुछ वर्ग के पास आवश्यक तरीके नहीं हैं, तो आप उन्हें अंतर्निहित रूपांतरण का उपयोग करके एक वर्ग में जोड़ सकते हैं

नीचे एक ताजा REPL सत्र।

scala> implicit def eitherW[A, B](e: Either[A, B]) = new {
     |   def map[B1](f: B => B1) = e.right map f
     |   def flatMap[B1](f: B => Either[A, B1]) = e.right flatMap f
     | }
eitherW: [A, B](e: Either[A,B])java.lang.Object{def map[B1](f: B => B1): Product 
with Either[A,B1] with Serializable; def flatMap[B1](f: B => Either[A,B1]):
Either[A,B1]}

scala> for {
     |   foo <- Right(1): Either[String, Int]
     |   bar <- Left("nope") : Either[String, Int]
     | } yield (foo.toString + bar)
res0: Either[String,java.lang.String] = Left(nope)




either