Is the Scalaz disjunction \/ meant to replace the standard library's Either?

1.7k views Asked by At

New to scalaz but am I imagining things here? Scalaz's / is meant to replace the standard library's Either but I am having problems getting the values of either sides. A simple test class comparing / to Either:

package com.example

import scalaz.\/
import scalaz.syntax.either._

class TestEither {
  def returnEitherScalaz(p: Int): \/[Int, String] = {
    if (p > 0)
      s"AOK".right
    else
      p.left
  }

  def returnEitherDefault(p: Int): Either[Int, String] = {
    if (p > 0)
      Right(s"AOK")
    else
      Left(p)
  }
}

object TestRunner {
  def main(args: Array[String]): Unit = {
    val te = new TestEither

    val testValue = 1

    val resultS = te.returnEitherScalaz(testValue)
    println("result=" + resultS)
    println("isRight=" + resultS.isRight)
    println("isLeft=" + resultS.isLeft)

    val rightS = resultS.right.getOrElse("not right")
    println("right=" + rightS)

    val leftS = resultS.left.getOrElse("not left")
    println("left=" + leftS)

    val resultD = te.returnEitherDefault(testValue)
    println("result=" + resultD)
    println("isRight=" + resultD.isRight)
    println("isLeft=" + resultD.isLeft)

    val rightD = resultD.right.getOrElse("not right")
    println("right=" + rightD)

    val leftD = resultD.left.getOrElse("not left")
    println("left=" + leftD)
  }
}

produces the following output for right (testValue = 1)

result=\/-(AOK)
isRight=true
isLeft=false
right=\/-(AOK)
left=not left
result=Right(AOK)
isRight=true
isLeft=false
right=AOK
left=not left

the left (testValue = 0)

result=-\/(0)
isRight=false
isLeft=true
right=-\/(0)
left=not left
result=Left(0)
isRight=false
isLeft=true
right=not right
left=0

Is this a bug in Scalaz's / or am I just crazy? I've tried from most recent Scala/Scalaz versions 2.12.1/7.2.8 back to 2.11.8/7.2.6.

1

There are 1 answers

0
Lodewijk Bogaards On

resultS.right does not return an Option[String], but the right disjunction of the disjunction (like when you're calling s"AOK".right). Since ScalaZ disjunctions are right leaning, the getOrElse function is also available to offer you a way of getting the right side. You are thus calling getOrElse on an disjunction, not on an Option.

With ScalaZ you don't access the left and right directly, but usually fold the result, map over it, pattern match, recover, etc. This would achieve the same result

def printRightLeft(l: Option[Int], r: Option[String]) = {
  println(s"right=${r.getOrElse("not right")}")
  println(s"left=${l.getOrElse("not left")}")
}

resultS
  .bimap(Option.apply, Option.apply)
  .bimap(printRightLeft(_, None), printRightLeft(None, _))