Composing Kleisli's with andThen isn't possible when the functor is Validated[X, ?] even though validated has an andThen method.
This is because Kleisli's andThen is an alias for flatMap and requires a FlatMap instance but Validated doesn't have a FlatMap instance (rightly so).
I don't know if it's reasonable, but there could be an AndThen type class in the same manner as FlatMap. The laws could be the same and for the vast majority of the instances the andThen method would just alias to flatMap. A default internal AndThenIsFlatMap trait could bake this into existing FlatMap instances. I don't know if this has any broader benefit outside of fixing the issue described above.
we have the Parallel work #1837 which could be used here. So, when you have a Parallel[F, G] you could do .andThen which lifts the applicative into a monad, flatmaps, then turns it back to the applicative.
Just to add to this, Kleisli also has a Parallel instance if the F[_] inside has a Parallel instance, so you can use Either for any thing you want to do using andThen and when composing things where you'd typically use Validated, use parMapN or parTraverse or something like that! :)
FWIW, here's an example I just ran in the REPL:
scala> val x = Kleisli((i: Int) => i.asRight[String])
x: cats.data.Kleisli[[+B]Either[String,B],Int,Int] = Kleisli($$Lambda$2585/1074814992@1f9843e5)
scala> val y = Kleisli((i: Int) => i.toDouble.asRight[String])
y: cats.data.Kleisli[[+B]Either[String,B],Int,Double] = Kleisli($$Lambda$2586/357402099@2a90f681)
scala> val z = x andThen y
z: cats.data.Kleisli[[+B]Either[String,B],Int,Double] = Kleisli(cats.data.Kleisli$$Lambda$2589/2011040303@4e1ff808)
scala> val w = Kleisli((d: Double) => if (d < 5.0) d.toString.asLeft[Double] else d.asRight[String])
w: cats.data.Kleisli[[+B]Either[String,B],Double,Double] = Kleisli($$Lambda$2590/1381774303@1dc0c104)
scala> val v = Kleisli((d: Double) => "Error".asLeft[Double])
v: cats.data.Kleisli[[+B]Either[String,B],Double,Double] = Kleisli($$Lambda$2591/1179268926@2206e39a)
scala> z andThen (v, w).parMapN(_ + _)
res4: cats.data.Kleisli[[+B]Either[String,B],Int,Double] = Kleisli(cats.data.Kleisli$$Lambda$2589/2011040303@3e52d414)
scala> res4.run(2)
res5: Either[String,Double] = Left(Error2.0)
scala> res4.run(6)
res6: Either[String,Double] = Left(Error)
Most helpful comment
we have the
Parallelwork #1837 which could be used here. So, when you have aParallel[F, G]you could do.andThenwhich lifts the applicative into a monad, flatmaps, then turns it back to the applicative.