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
}