2

When I use Either type in Scalaz, it is a very good design, but method getOrElse would lose type inference.

val either = ~3.right[String] | "123" // either: String

val either = 3.right[String] | "123" // either: Any

why val either = 3.right[String] | "123" not refer Int, but Any occurred.

Is it a flaw or it is part of design ?

Many thanks in advance

Xiaohe Dong
  • 4,953
  • 6
  • 24
  • 53

2 Answers2

3

3.right[String] is of type \/-[String, Int] i.e. you have an Int on the right and a String on the left. However you're also providing a String as fallback value for the right side.

The compiler looks then for the lowest common supertype of String and Int, which happens to be Any.

Remember that the type parameter will give information about the "missing" side: if you have a right it will mark the type of the left, and vice versa.

In the first case you're saying: I have a left Int, my right will be a String (which is consistent with "123" passed as right fallback value)

In the latter you're saying: I have a right Int, my left will be a String, but you're then providing a String as a right.

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
0

The reason this happens is the type constraint that BB >: B in the definition of | and \/. See https://github.com/scalaz/scalaz/blob/series/7.2.x/core/src/main/scala/scalaz/Either.scala#L202-L210

sealed abstract class \/[+A, +B] {
...
  def getOrElse[BB >: B](x: => BB): BB = ...

  def |[BB >: B](x: => BB): BB = ...
...
}

BB >: B means that BB must be a super type of B. In your example, B is Int and "123" is String. As @Gabriele Petronella pointed out, BB is inferred to be the "lowest common supertype" of Int and String, which happens to be Any.

If the signature were the following instead, your example would fail to compile.

sealed abstract class \/[+A, +B] {
...
  def getOrElse[B](x: => B): B = ...

  def |[B](x: => B): B = ...
...
}

Given the definitions above, x: B, which in your example is Int. "123" is not Int.

drstevens
  • 2,903
  • 1
  • 21
  • 30