Reputation: 853
I wanted to implement a similar type called Result
to the Either
type. The main difference is, that the Left side of the Result
type should always be a List of something. What would be the right type definition for this? I tried having something like that:
sealed trait Result[List, +A] {
def map[B](f: A => B): Result[List, B] = this match {
case Failure(err) => Failure(err)
case Success(value) => Success(f(value))
}
def apply[B](f: Result[List, A => B]): Result[List, B] = (f, this) match {
case (Failure(fE), Failure(aE)) => Failure(fE ::: aE)
case ...
}
}
final case class Failure[+E](errors: List[E]) extends Result[List[E], Nothing]
final case class Success[+A](value: A) extends Result[Nothing, A]
But this runs in an error in the map function saying Failure[Any] does not equal Result[List, B]
and Success[B] does not equal Result[List, B]
. Is the type definition Result[List, +A]
already wrong, should I use a higher-kinded type like List[_]
instead?
Upvotes: 0
Views: 272
Reputation: 44977
If you want that the left side is always List
of something, then there is no need to abstract over the List
. Abstract over E
:
sealed trait Result[+E, +A] {
def map[B](f: A => B): Result[E, B] = this match {
case Failure(err) => Failure(err)
case Success(value) => Success(f(value))
}
def apply[B, F >: E](f: Result[F, A => B]): Result[F, B] = (f, this) match {
case (Failure(fE), Failure(aE)) => Failure(fE ::: aE)
case (Failure(fE), _) => Failure(fE)
case (_, Failure(aE)) => Failure(aE)
case (Success(fS), Success(tS)) => Success(fS(tS))
}
}
case class Failure[+E](errors: List[E]) extends Result[E, Nothing]
case class Success[+A](value: A) extends Result[Nothing, A]
Note that it looks as if you are reinventing some standard Applicative
s from Scalaz/Cats.
Upvotes: 2