New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

definition inside a for comprehension based on an Either fails to compile #5793

Closed
scabug opened this Issue May 13, 2012 · 5 comments

Comments

Projects
None yet
1 participant
@scabug
Copy link

scabug commented May 13, 2012

Including a definition in a for comprehension works if the comprehension is using Option, but the compiler complains about a for comprehension with Either (RightProjection).

Using for comprehensions makes for very readable code, and flowing though errors via Either seems like it ought to be the right thing to do.

Example:

def opt:Option[Char] = Some('e')
def f(c:Char):String = "ha"
def either:Either[Int,Char] = Right('r')

val optComprehensionWithAssignment:Option[Int] =
  for {
    c <- opt
    x = c.toInt
  } yield x

val eitherComprehensionNoAssignment:Either[Int,String] = 
  for { 
    c <- either.right
  } yield {
    val s = f(c)
    s
  }

val eitherComprehensionWithAssighment:Either[Int,String] = 
  for { 
    c <- either.right
    s = f(c)                // doesn't compile
  } yield s


val workaround:Either[Int,String] = 
  for { 
    c <- either.right
    s <- Right(f(c)).right       // workaround's a bit awkward
  } yield s
@scabug

This comment has been minimized.

Copy link
Author

scabug commented May 13, 2012

Imported From: https://issues.scala-lang.org/browse/SI-5793?orig=1
Reporter: Lee Mighdoll (mighdoll)

@scabug

This comment has been minimized.

Copy link
Author

scabug commented May 13, 2012

@retronym said:
You are essentially trying to call:

scala> either.right.map(x => x).map(x => x)
<console>:9: error: value map is not a member of Either[Int,Char] with Product with Serializable
              either.right.map(x => x).map(x => x)
                                       ^

But Either#RightProjection#map returns an Either, which doesn't have a map method.

You can enrich Either to have a right-biased set of map/flatMap/foreach methods, along these lines (I'm using Scala 2.10 implicit classes for brevity, but the same is possible in 2.9.x with a class and an implicit conversion):

scala> implicit class RightBiasedEither[A, B](val e: Either[A, B]) extends AnyVal {
     |   def foreach[U](f: B => U): Unit = e.right.foreach(f)
     |   def map[C](f: B => C): Either[A, C] = e.right.map(f)
     |   def flatMap[C](f: B => Either[A, C]) = e.right.flatMap(f)  
     | }
defined class RightBiasedEither

scala> 

scala> def f(c:Char):String = "ha"
f: (c: Char)String

scala> def either:Either[Int,Char] = Right('r')
either: Either[Int,Char]

scala>   for { 
     |     c <- either
     |     s = f(c)
     |   } yield s
res0: Either[Int,String] = Right(ha)

@scabug scabug closed this May 13, 2012

@scabug

This comment has been minimized.

Copy link
Author

scabug commented May 14, 2012

Lee Mighdoll (mighdoll) said:
Thanks Jason. That's very helpful. I understand the flaw in Either now. Your solution is nice both to explain and to try out.

That the stock unbiased Either requires a bit more syntax to use the RightProjection/LeftProjection is apparent from the api, but because of this design flaw it's hard to recommend Either.

Is there an open issue on fixing Either? Or a consensus that it's not fixable? Seems like the standard lib should get some combination of a fix, interim documentation, or a replacement.

@scabug

This comment has been minimized.

Copy link
Author

scabug commented May 14, 2012

@scabug

This comment has been minimized.

Copy link
Author

scabug commented May 28, 2012

Rob Dickens (robcd) said:
Lee, Jason,

Have just come up with a version of Either which fixes this. Please would you take a look and let me know what you think:

http://robsscala.blogspot.co.uk/2012/05/fixing-scalaeither-leftrightmap-returns.html

Cheers, Rob

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment