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




monads typeclass (2)

जैसा कि मैं इसे समझता हूं, "सिंटैक्स के लिए स्काला" हास्केल के मोनडिक "डू" सिंटैक्स के समान है। स्काला में, "के लिए" सिंटैक्स का उपयोग अक्सर 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 ?) कैसे? मान लीजिए कि मैं अपने स्वयं के "मोनड उदाहरण" प्रदान करना चाहता था, तो मैं यह कैसे कर सकता था?


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

हां, लेकिन तीसरे पक्ष के आयात के माध्यम से: स्कलाज़ 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)

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)






either