Either
Either / Disjunction
Use Constructor Methods
To create Either type value, instead of doing Right(value) or Left(error), use data constructors provided by FP libraries like Scalaz and Cats.
Using Right() and Left() exposes the data not type.
Right(1)
// res0: Right[Nothing, Int] = Right(value = 1)
Right[String, Int](1)
// res1: Right[String, Int] = Right(value = 1)
Left("Some error")
// res2: Left[String, Nothing] = Left(value = "Some error")
Left[String, Int]("Some error")
// res3: Left[String, Int] = Left(value = "Some error")
// You can List[Either[*, Int]] not List[Right[*, Int]]
List(Right(1), Right(2))
// res4: List[Right[Nothing, Int]] = List(Right(value = 1), Right(value = 2))
So use the constructor methods for Either from Cats or the ones from \/ (Disjunction) from Scalaz.
- Cats
- Scalaz
import cats.syntax.either._
1.asRight[String]
// res6: Either[String, Int] = Right(value = 1)
"Some error".asLeft[Int]
// res7: Either[String, Int] = Left(value = "Some error")
List(1.asRight[String], 2.asRight[String])
// res8: List[Either[String, Int]] = List(Right(value = 1), Right(value = 2))
import scalaz._, Scalaz._
1.right[String]
// res10: String \/ Int = \/-(b = 1)
"Some error".left[Int]
// res11: String \/ Int = -\/(a = "Some error")
List(1.right[String], 2.right[String])
// res12: List[String \/ Int] = List(\/-(b = 1), \/-(b = 2))
- Cats
- Scalaz
import cats._
// No
def foo[F[_] : Applicative](n: Int): F[Either[String, Int]] = {
val r = Applicative[F].pure(Right(n))
r
}
// error: type mismatch;
// found : r.type (with underlying type F[scala.util.Right[Nothing,Int]])
// required: F[Either[String,Int]]
// Note: scala.util.Right[Nothing,Int] <: Either[String,Int], but type F is invariant in type _.
// You may wish to define _$$1 as +_$$1 instead. (SLS 4.5)
// r
// ^
import cats._
import cats.syntax.either._
// Yes
def foo[F[_] : Applicative](n: Int): F[Either[String, Int]] = {
val r = Applicative[F].pure(n.asRight[String])
r
}
import scalaz._, Scalaz._
// No
def foo[F[_] : Applicative](n: Int): F[Either[String, Int]] = {
val r = Applicative[F].pure(Right(n))
r
}
// error: type mismatch;
// found : r.type (with underlying type F[scala.util.Right[Nothing,Int]])
// required: F[Either[String,Int]]
// Note: scala.util.Right[Nothing,Int] <: Either[String,Int], but type F is invariant in type _.
// You may wish to define _$$2 as +_$$2 instead. (SLS 4.5)
// r
// ^
import scalaz._
import Scalaz._
// Yes
def foo[F[_] : Applicative](n: Int): F[String \/ Int] = {
val r = Applicative[F].pure(n.right[String])
r
}
- Cats
- Scalaz
import cats._
// No
def foo[F[_] : Applicative](n: Int): F[Either[String, Int]] = {
val r = Applicative[F].pure(Left("Some error"))
r
}
// error: type mismatch;
// found : r.type (with underlying type F[scala.util.Left[String,Nothing]])
// required: F[Either[String,Int]]
// Note: scala.util.Left[String,Nothing] <: Either[String,Int], but type F is invariant in type _.
// You may wish to define _$$3 as +_$$3 instead. (SLS 4.5)
// r
// ^
import cats._
import cats.syntax.either._
// Yes
def foo[F[_] : Applicative](n: Int): F[Either[String, Int]] = {
val r = Applicative[F].pure("Some error".asLeft[Int])
r
}
import scalaz._, Scalaz._
// No
def foo[F[_] : Applicative](n: Int): F[Either[String, Int]] = {
val r = Applicative[F].pure(Left("Some error"))
r
}
// error: type mismatch;
// found : r.type (with underlying type F[scala.util.Left[String,Nothing]])
// required: F[Either[String,Int]]
// Note: scala.util.Left[String,Nothing] <: Either[String,Int], but type F is invariant in type _.
// You may wish to define _$$4 as +_$$4 instead. (SLS 4.5)
// r
// ^
import scalaz._
import Scalaz._
// Yes
def foo[F[_] : Applicative](n: Int): F[String \/ Int] = {
val r = Applicative[F].pure("Some error".left[Int])
r
}