fs2 dropWhile with X => IO[Boolean] - scala

I can write something like the following and it works just as it should (it yields 10):
import cats.effect.IO
import cats.effect.unsafe.implicits.global
val zz: fs2.Stream[IO, Int] = fs2.Stream.iterate[IO, Int](1)(_+1).map(_*2)
val qq: IO[Int] = zz.dropWhile(_ < 10).take(1).compile.toList.map(_.head)
qq.unsafeRunSync()
However, supposing that, instead of a predicate like _ < 10 which returns Boolean, I have a predicate that returns an IO[Boolean]. Is there an alternative form of dropWhile which could handle this situation? I don't want to have to do something like unsafeRunSync() inside the predicate just so that it can yield a Boolean.
Clearly, this is a toy case, not the actual problem that I'm working on.

You can easily define that combinator yourself:
def dropWhileEval[A](sa: Stream[IO, A])(p: A = IO[Boolean]): Stream[IO, A] =
sa.evalMap(a => p(a).map(b => (b, a))).dropWhile(_._1).map(_._2)

This answer is based on the accepted answer by #Luis Miguel Mejia Suárez. But there is a tiny typo in that answer and, essentially, I changed the question after posting the original. So here's the final (toy) code:
import cats.effect.IO
import fs2.{Pure, Stream}
import cats.effect.unsafe.implicits.global
val fLessThan10: Int => Boolean = _ < 10
val fLessThan10_lifted: IO[Int] => IO[Boolean] = _ map fLessThan10
def dropWhileEval[A](sa: Stream[IO, IO[A]])(p: IO[A] => IO[Boolean]): fStream[IO, IO[A]] =
sa.evalMap(a => p(a).map(b => (b, a))).dropWhile(_._1).map(_._2)
val zz: Stream[IO, IO[Int]] = Stream.iterate[IO, Int](1)(_+1).map(x => IO(x*2))
val yy: Stream[IO, IO[Int]] = dropWhileEval[Int](zz)(fLessThan10_lifted).take(1)
val result: IO[List[Int]] = yy.evalMap(identity).compile.toList
#result.unsafeRunSync()

Related

Convert List[Either[A, B]] to Either[List[A], List[B]]

How to convert List[Either[String, Int]] to Either[List[String], List[Int]] using a method similar to cats sequence? For example, xs.sequence in the following code
import cats.implicits._
val xs: List[Either[String, Int]] = List(Left("error1"), Left("error2"))
xs.sequence
returns Left(error1) instead of required Left(List(error1, error2)).
KevinWrights' answer suggests
val lefts = xs collect {case Left(x) => x }
def rights = xs collect {case Right(x) => x}
if(lefts.isEmpty) Right(rights) else Left(lefts)
which does return Left(List(error1, error2)), however does cats provide out-of-the-box sequencing which would collect all the lefts?
Another variation on the same theme (similar to this answer), all imports included:
import scala.util.Either
import cats.data.Validated
import cats.syntax.traverse._
import cats.instances.list._
def collectErrors[A, B](xs: List[Either[A, B]]): Either[List[A], List[B]] = {
xs.traverse(x => Validated.fromEither(x.left.map(List(_)))).toEither
}
If you additionally import cats.syntax.either._, then the toValidated becomes available, so you can also write:
xs.traverse(_.left.map(List(_)).toValidated).toEither
and if you additionally replace the left.map by bimap(..., identity), you end up with #DmytroMitin's wonderfully concise solution.
This solution doesn't use cats, but from Scala 2.13, you can use of partitionMap:
def convert[L,R](input: List[Either[L,R]]): Either[List[L], List[R]] = {
val (left, right) = input.partitionMap(identity)
if (left.isEmpty) Right(right) else Left(left)
}
println(convert(List(Left("error1"), Left("error2"))))
// Left(List(error1, error2))
println(convert(List(Right(1), Left("2"), Right(3), Left("4"))))
// Left(List(2, 4))
println(convert(List(Right(1), Right(2), Right(3), Right(4))))
// Right(List(1, 2, 3, 4))
Try
xs.traverse(_.toValidated.bimap(List(_), identity)).toEither
// List(Left("error1"), Left("error2")) => Left(List("error1", "error2"))
// List(Right(10), Right(20)) => Right(List(10, 20))
// List(Right(10), Left("error2")) => Left(List("error2"))

How to flatten a sequence of cats' ValidatedNel values

I need to flatten a sequence of cats.data.ValidatedNel[E, T] values to a single ValidatedNel value:
val results: Seq[cats.data.ValidatedNel[E, T]] = ???
val flattenedResult: cats.data.ValidatedNel[E, T]
I can do it like this:
import cats.std.list._, cats.syntax.cartesian._
results.reduce(_ |#| _ map { case _ => validatedValue })
but wonder if a pre-defined library methods exists.
It depends on how you want to combine them (what is validatedValue in your question ?)
import cats.data.{Validated, ValidatedNel}
import cats.implicits._
val validations1 = List(1.validNel[String], 2.valid, 3.valid)
val validations2 = List(1.validNel[String], "kaboom".invalidNel, "boom".invalidNel)
If you want to combine the Ts, you can use Foldable.combineAll which uses a Monoid[T] :
val valSum1 = validations1.combineAll
// Valid(6)
val valSum2 = validations2.combineAll
// Invalid(OneAnd(kaboom,List(boom)))
If you want to get a ValidationNel[String, List[T]], you can use Traverse.sequence :
val valList1: ValidatedNel[String, List[Int]] = validations1.sequence
// Valid(List(1, 2, 3))
val valList2: ValidatedNel[String, List[Int]] = validations2.sequence
// Invalid(OneAnd(kaboom,List(boom)))
If you don't care about the result, which seems to be the case, you can use Foldable.sequence_.
val result1: ValidatedNel[String, Unit] = validations1.sequence_
// Valid(())
val result2: ValidatedNel[String, Unit] = validations2.sequence_
// Invalid(OneAnd(kaboom,List(boom)))
validations1.sequence_.as(validatedValue) // as(x) is equal to map(_ => x)

Efficient and/or idiomatic way to turn Seq[Either[String, Int]] to (Seq[String], Seq[Int])

Slightly simplifying, my problem comes from a list of strings input that I want to parse with a function parse returning Either[String,Int].
Then list.map(parse) returns a list of Eithers. The next step in the program is to format an error message summing up all the errors or passing on the list of parsed integers.
Lets call the solution I'm looking for partitionEithers.
Calling
partitionEithers(List(Left("foo"), Right(1), Left("bar")))
Would give
(List("foo", "bar"),List(1))
Finding something like this in the standard library would be best. Failing that some kind of clean, idiomatic and efficient solution would be best. Also some kind of efficient utility function I could just paste into my projects would be ok.
I was very confused between these 3 earlier questions. As far as I can tell, neither of those questions matches my case, but some answers there seem to contain valid answers to this question.
Scala collections offer a partition function:
val eithers: List[Either[String, Int]] = List(Left("foo"), Right(1), Left("bar"))
eithers.partition(_.isLeft) match {
case (leftList, rightList) =>
(leftList.map(_.left.get), rightList.map(_.right.get))
}
=> res0: (List[String], List[Int]) = (List(foo, bar),List(1))
UPDATE
If you want to wrap it in a (maybe even somewhat type safer) generic function:
def partitionEither[Left : ClassTag, Right : ClassTag](in: List[Either[Left, Right]]): (List[Left], List[Right]) =
in.partition(_.isLeft) match {
case (leftList, rightList) =>
(leftList.collect { case Left(l: Left) => l }, rightList.collect { case Right(r: Right) => r })
}
You could use separate from MonadPlus (scalaz) or MonadCombine (cats) :
import scala.util.{Either, Left, Right}
import scalaz.std.list._
import scalaz.std.either._
import scalaz.syntax.monadPlus._
val l: List[Either[String, Int]] = List(Right(1), Left("error"), Right(2))
l.separate
// (List[String], List[Int]) = (List(error),List(1, 2))
I don't really get the amount of contortions of the other answers. So here is a one liner:
scala> val es:List[Either[Int,String]] =
List(Left(1),Left(2),Right("A"),Right("B"),Left(3),Right("C"))
es: List[Either[Int,String]] = List(Left(1), Left(2), Right(A), Right(B), Left(3), Right(C))
scala> es.foldRight( (List[Int](), List[String]()) ) {
case ( e, (ls, rs) ) => e.fold( l => ( l :: ls, rs), r => ( ls, r :: rs ) )
}
res5: (List[Int], List[String]) = (List(1, 2, 3),List(A, B, C))
Here is an imperative implementation mimicking the style of Scala collection internals.
I wonder if there should something like this in there, since at least I run into this from time to time.
import collection._
import generic._
def partitionEithers[L, R, E, I, CL, CR]
(lrs: I)
(implicit evI: I <:< GenTraversableOnce[E],
evE: E <:< Either[L, R],
cbfl: CanBuildFrom[I, L, CL],
cbfr: CanBuildFrom[I, R, CR])
: (CL, CR) = {
val ls = cbfl()
val rs = cbfr()
ls.sizeHint(lrs.size)
rs.sizeHint(lrs.size)
lrs.foreach { e => evE(e) match {
case Left(l) => ls += l
case Right(r) => rs += r
} }
(ls.result(), rs.result())
}
partitionEithers(List(Left("foo"), Right(1), Left("bar"))) == (List("foo", "bar"), List(1))
partitionEithers(Set(Left("foo"), Right(1), Left("bar"), Right(1))) == (Set("foo", "bar"), Set(1))
You can use foldLeft.
def f(s: Seq[Either[String, Int]]): (Seq[String], Seq[Int]) = {
s.foldRight((Seq[String](), Seq[Int]())) { case (c, r) =>
c match {
case Left(le) => (le +: r._1, r._2)
case Right(ri) => (r._1 , ri +: r._2)
}
}
}
val eithers: List[Either[String, Int]] = List(Left("foo"), Right(1), Left("bar"))
scala> f(eithers)
res0: (Seq[String], Seq[Int]) = (List(foo, bar),List(1))

How to accumulate scala.util.Try failures?

Suppose I need to accumulate function failures. I can do it easily with scalaz:
val foo: String => Throwable\/Int = {s => \/.fromTryCatchNonFatal(s.toInt)}
val v1 = foo("abc").validation.toValidationNel
val v2 = foo("xyz").validation.toValidationNel
val v = (v1 |#| v2) {_ + _}
val e = v.toDisjunciton
Now I've got a function, which returns scala.util.Try instead of scalaz.\/
val f: String => Try[Int] = {s => Try(s.toInt)}
What is best way to accumulate the scala.util.Try failures ? Do I need to convert scala.util.Try to scalaz.Validation and visa versa manually?
Maybe this may help you:
def accumulate[T](tries:Try[T]*) = tries.collect {case Failure(t) => t}
scalaz 7.2.x contains https://github.com/scalaz/scalaz/blob/122e5f9dfc3fbe9189d1f817e703c78047fbb3ef/core/src/main/scala/scalaz/std/Try.scala#L14-L15 which you can use as an idea to create an implicit class which does the conversion to Validation and ValidationNel for you.

Scala, partial functions

Is there any way to create a PartialFunction except through the case statement?
I'm curious, because I'd like to express the following (scala pseudo ahead!)...
val bi = BigInt(_)
if (bi.isValidInt) bi.intValue
... as a partial function, and doing
val toInt : PartialFunction[String, Int] = {
case s if BigInt(s).isValidInt => BigInt(s).intValue
}
seems redundant since I create a BigInt twice.
Not sure I understand the question. But here's my attempt: Why not create an extractor?
object ValidBigInt {
def unapply(s: String): Option[Int] = {
val bi = BigInt(s)
if (bi.isValidInt) Some(bi.intValue) else None
}
}
val toInt: PartialFunction[String, Int] = {
case ValidBigInt(i) => i
}
The other option is (and that may answer the question as to whether one can create PartialFunction other than with a case literal):
val toInt = new PartialFunction[String, Int] {
def isDefinedAt(s: String) = BigInt(s).isValidInt
def apply(s: String) = BigInt(s).intValue
}
However since the idea of a partial function is that it's only partially defined, in the end you will still do redundant things -- you need to create a big int to test whether it's valid, and then in the function application you create the big int again...
I saw a project at Github that tried to come around this by somewhat caching the results from isDefinedAt. If you go down to the benchmarks, you'll see that it turned out to be slower than the default Scala implementation :)
So if you want to get around the double nature of isDefinedAt versus apply, you should just go straight for a (full) function that provides an Option[Int] as result.
I think you're looking for lift/unlift. lift takes a partial function and turns it into a function that returns an Option. Unlift takes a function with one argument that returns an option, and returns a partial function.
import scala.util.control.Exception._
scala> def fn(s: String) = catching(classOf[NumberFormatException]) opt {BigInt(s)}
fn: (s: String)Option[scala.math.BigInt]
scala> val fnPf = Function.unlift(fn)
fnPf: PartialFunction[String,scala.math.BigInt] = <function1>
scala> val fn = fnPf.lift
fn: String => Option[scala.math.BigInt] = <function1>
Closely related, you also want to look at this answer for information about cond and condOpt:
scala> import PartialFunction._
import PartialFunction._
scala> cond("abc") { case "def" => true }
res0: Boolean = false
scala> condOpt("abc") { case x if x.length == 3 => x + x }
res1: Option[java.lang.String] = Some(abcabc)
You can write out a PartialFunction "longhand" if you'd like:
object pf extends PartialFunction[Int,String] {
def isDefinedAt(in: Int) = in % 2 == 0
def apply(in: Int) = {
if (in % 2 == 0)
"even"
else
throw new MatchError(in + " is odd")
}
Okay, I got this
import java.lang.NumberFormatException
import scala.util.control.Exception._
val toInt: PartialFunction[String, Int] = {
catching(classOf[NumberFormatException]) opt BigInt(_) match {
case Some(bi) if bi.isValidInt => bi.intValue
}
}
How about this?
val toInt: PartialFunction[String, Int] = (s: String) => BigInt(s) match {
case bi if bi.isValidInt => bi.intValue
}