Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use flatMap on List[Either] in Scala

Either is right-biased ince Scala 2.12 which allows it to be used in for/yield blocks without projection just like Option. But apparently this isn't enough to behave like Option when used with flatMap.

object Main {

  def main(args: Array[String]): Unit = {

    val nums = List.range(1,10)

    println(nums.flatMap(evenOption))
    println(nums.flatMap(evenEither)) // fails

  }

  def evenOption(x: Int): Option[Int]       = if (x % 2 == 0) Some(x) else None
  def evenEither(x: Int): Either[String, Int] = if (x % 2 == 0) Right(x) else Left("not even")

}

My minimal category theory knowledge makes me think that Either is not a monad and therefore this fails? Or how else can I make the example above work?

like image 372
TomTom Avatar asked Jan 17 '17 18:01

TomTom


1 Answers

It has nothing to do with Either being or not being a monad. When you're executing flatMap method on some data structure, the function that you're passing into has to return an instance of that data structure. So when you're flatmapping over an Option, your function has to return an Option. If you're flatmapping over a Future, your function has to return a Future. The same goes with a List: flatmapping over a list has to return a List itself. So why does your List.flatMap(Option) work and List.flatMap(Either) doesn't? Because there's an implicit conversion from an Option to an Iterable (Option.option2Iterable), and that conversion took place in your example. There's no such conversion for the Either datatype (unless you create it yourself).

like image 71
Paweł Jurczenko Avatar answered Oct 15 '22 12:10

Paweł Jurczenko