Почему getOrElse теряет вывод типа в scalaz

Когда я использую тип Either в Scalaz, это очень хороший дизайн, но метод getOrElse теряет вывод типа.

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

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

почему val либо = 3.right [String] | «123» не относится к Int, но имеет место Any.

Это недостаток или часть дизайна?

Спасибо заранее


person Xiaohe Dong    schedule 10.10.2014    source источник


Ответы (2)


3.right[String] относится к типу \/-[String, Int], т.е. у вас Int справа и String слева. Однако вы также предоставляете String в качестве резервного значения для правой стороны.

Затем компилятор ищет самый низкий общий супертип String и Int, которым оказывается Any.

Помните, что параметр типа предоставит информацию о «отсутствующей» стороне: если у вас есть right, он будет отмечать тип left, и наоборот.

В первом случае вы говорите: у меня левый Int, мой правый будет String (что согласуется с "123", переданным как правое резервное значение)

В последнем случае вы говорите: у меня правая Int, моя левая будет String, но тогда вы указываете String как правую.

person Gabriele Petronella    schedule 10.10.2014

Причина, по которой это происходит, - это ограничение типа BB >: B в определении | и \/. См. 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 означает, что BB должен быть супертипом B. В вашем примере B - это Int, а "123" - это String. Как отметила @Gabriele Petronella, BB считается "самым низким общим супертипом" для Int и String, которым оказывается Any.

Если бы подпись была следующей, ваш пример не удалось бы скомпилировать.

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

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

Учитывая приведенные выше определения, x: B, в вашем примере это Int. «123» не Int.

person drstevens    schedule 10.10.2014