Я могу использовать =
в scala for-comprehension (как указано в разделе6.19SLS) следующим образом:
Предположим, у меня есть какая-то функция String => Option[Int]
:
scala> def intOpt(s: String) = try { Some(s.toInt) } catch { case _ => None }
intOpt: (s: String)Option[Int]
Тогда я могу использовать ее таким образом
scala> for {
| str <- Option("1")
| i <- intOpt(str)
| val j = i + 10 //Note use of = in generator
| }
| yield j
res18: Option[Int] = Some(11)
Как я понял что это было по существу эквивалентно:
scala> Option("1") flatMap { str => intOpt(str) } map { i => i + 10 } map { j => j }
res19: Option[Int] = Some(11)
То есть встроенный генератор был способом внедрения map
int o последовательность вызовов flatMap
. Все идет нормально.
Что я на самом деле хочу сделать: использовать for-comprehension, аналогичный предыдущему примеру, используя монаду Someone
.
Однако, если мы используем его в аналогичной цепочке, но на этот раз с помощью Либо.RightProjection
монада/функтор, это не работает:
scala> def intEither(s: String): Either[Throwable, Int] =
| try { Right(s.toInt) } catch { case x => Left(x) }
intEither: (s: String)Either[Throwable,Int]
Тогда используйте:
scala> for {
| str <- Option("1").toRight(new Throwable()).right
| i <- intEither(str).right //note the "right" projection is used
| val j = i + 10
| }
| yield j
:17: error: value map is not a member of Product with Serializable with Either[java.lang.Throwable,(Int, Int)]
i <- intEither(str).right
^
Проблема как-то связана с функцией, которую правая проекция ожидает в качестве аргумента для своей flatMap
метод (т.е. он ожидает R => Либо[L, R]
). Но модифицируя, чтобы не вызывать right
во втором генераторе, он все равно не будет компилироваться.
scala> for {
| str <- Option("1").toRight(new Throwable()).right
| i <- intEither(str) // no "right" projection
| val j = i + 10
| }
| yield j
:17: error: value map is not a member of Either[Throwable,Int]
i <- intEither(str)
^
Но теперь я запутался вдвойне. Следующее работает отлично:
scala> for {
| x <- Right[Throwable, String]("1").right
| y <- Right[Throwable, String](x).right //note the "right" here
| } yield y.toInt
res39: Either[Throwable,Int] = Right(1)
Но это не так:
scala> Right[Throwable, String]("1").right flatMap { x => Right[Throwable, String](x).right } map { y => y.toInt }
:14: error: type mismatch;
found : Either.RightProjection[Throwable,String]
required: Either[?,?]
Right[Throwable, String]("1").right flatMap { x => Right[Throwable, String](x).right } map { y => y.toInt }
^
Я думал, что они эквивалентны
=
в для понимания через Либо
?