Вопрос по – Использование Eithers с Scala «для» синтаксиса

37

Error: User Rate Limit ExceededListError: User Rate Limit ExceededOptionError: User Rate Limit ExceededEitherError: User Rate Limit Exceeded

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

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

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

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

Error: User Rate Limit ExceededList()Error: User Rate Limit ExceededOptionError: User Rate Limit ExceededNoneError: User Rate Limit ExceededscalazError: User Rate Limit Exceeded

@virtualeyes совершенно верно. Почти все мои вопросы не связаны с тем, чтобы видеть или давать ответ на чужой вопрос. Dan Burton
отличный вопрос, @DanBurton, предположим, связанный с вашим эпическим ответом,stackoverflow.com/a/10866383/185840 со вчерашнего дня virtualeyes

Ваш Ответ

3   ответа
8

Either являетсясейчас правы

Отдокументация:

As Either defines the methods map and flatMap, it can also be used in for comprehensions:

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)
15

Да, но через сторонний импорт: Scalaz предоставляетMonad экземпляр для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 - также из Скалаза.

Edit:

Я пропустил этот твой вопрос.

Suppose I wanted to provide my own "monad instance" for Either, how could I do that?

Scalafor Понимания просто переводятся на.map, .flatMap, .withFilter, а также.filter .foreach звонки на вовлеченных объектах. (Вы можете найти полную схему переводаВот. Так что, если у какого-то класса нет необходимых методов, вы можетеadd их в класс, используя неявные преобразования.

Свежая сессия 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)
так нет ли возможности использовать если охранники? Трудно, если бы это было так, было бы достаточно мощно объединить Либо с включенным для понимания с охраной. Я могу заставить его скомпилировать, после защиты, с помощью "e & lt; - any.right.toOption" quot;
@missingfaktor Я не вижу никаких упоминаний о.filter Метод в версии 2.9 спецификации:The precise meaning of generators and guards is defined by translation to invocations of four methods: map, withFilter, flatMap, and foreach.
@virtualeyes, да, я хорошо знаком с техникой. Что насчет этого? Кажется, это не связано сfilterилиif-защиты в любом случае.
@virtualeyes: & quot; значит, нет способа использовать if guard? & quot; Конечно, есть. Просто сутенер.filter а также.withFilter наEither с любым поведением, которое вы хотите поддержать.
k, придется погрузиться в предоставленную вами ссылку, это продвинутый pimping ;-) Возможно, вы думаете, что возможно что-то, что не с Either включено для понимания; проверьте отличный ответ Хаскелла Дэна Бертона на мой вопрос об условном ветвлении if / else со встроенным возвратом (stackoverflow.com/a/10866383/185840). В основном, пытаясь сделать то же самое с Either for {...}, где вы получаете результат Left / Right против Some / None
50

in scala 2.11 and earlier так какEither это не монада Несмотря на то, что речь идет о правомерном смещении, вы не можете использовать его для понимания: вы должны получитьLeftProject или жеRightProjectionкак показано ниже:

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

Что возвращаетLeft("nope"), Кстати.

В Scalaz вы заменяетеEither сValidation, Интересный факт:EitherПервоначальный автор - Тони Моррис, один из авторов Scalaz. Он хотел сделатьEither предвзято, но коллега убедил в обратном.

больше информации о том, почему он былconvinced otherwise by a colleague.?
@KevinMeredith Я не помню и не думаю, что когда-либо знал об этом. Я думаю, что услышал это от самого Тони, «о, почему я позволил этому случиться» вроде тона, но это было давно.
Да ! Право смещено, как на самом деле в Хаскеле. Вы можете использовать FlatMap Либо, но только справа. Потому что экземпляр Functor дляEither основывается наEither a ^^

Похожие вопросы