I am a beginner in the work of functional programming and I have a sequence of ValidationNEL[A,B] and I would like to accumulate the errors into a new ValidationNEL[A,B]. This depends on the fact that B
is a mutable data structure coming from legacy code, and so it would be oververbose to hold a Seq[B].
I know from other posts that cumulating errors and success is possible through the sequence method: Processing a list of Scalaz6 Validation
From my understanding it all comes to writing a proper Applicative and maybe a proper Traverse.
trait MA[M[_], A] extends PimpedType[M[A]] with MASugar[M, A] {
def sequence[N[_], B](implicit a: A <:< N[B], t: Traverse[M], n: Applicative[N]): N[M[B]] =
traverse((z: A) => (z: N[B]))
def traverse[F[_],B](f: A => F[B])(implicit a: Applicative[F], t: Traverse[M]): F[M[B]] =
t.traverse(f, value)
}
How do I start? When I tried to look into Scalaz source code to find out how to implement my Applicative, I got extremely confused. I was not even able to find out which applicative allows accumulating both failures and success in Validation.
Late to the party, but as of Scalaz 7.0.4, we can do this:
def takeLastSuccess[A, B](seq: Seq[ValidationNel[A, B]]) = {
implicit val useLast = Semigroup.lastSemigroup[B]
seq reduceLeft (_ +++ _)
}
Now that I understand your question a little better, this is pretty straight forward:
def takeLastSuccess[A, B](seq:Seq[ValidationNEL[A, B]]) =
seq.sequence[({type l[a] = ValidationNEL[A, a]})#l, B].map(_.last)
When you sequence this Scala has some trouble with the types so you need to use a type lambda. Sequence is a nice shortcut to go from Seq[Something[X]] to Something[Seq[X]]. Finally, we just map the success and get the last B from the sequence of B's.
Going off the example from the post you cited, here's what I get from the REPL:
scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._
scala> type ExceptionsOr[A] = ValidationNEL[Exception, A]
defined type alias ExceptionsOr
scala> val successResults: Seq[ExceptionsOr[Int]] = Seq(
| "13".parseInt.liftFailNel, "42".parseInt.liftFailNel
| )
successResults: Seq[ExceptionsOr[Int]] = List(Success(13), Success(42))
scala> val failResults: Seq[ExceptionsOr[Int]] = Seq(
| "13".parseInt.liftFailNel, "a".parseInt.liftFailNel, "b".parseInt.liftFailNel
| )
failResults: Seq[ExceptionsOr[Int]] = List(Success(13), Failure(NonEmptyList(java.lang.NumberFormatException: For input string: "a")), Failure(NonEmptyList(java.lang.NumberFormatException: For input string: "b")))
scala> def takeLastSuccess[A, B](seq:Seq[ValidationNEL[A, B]]) = seq.sequence[({type l[a] = ValidationNEL[A, a]})#l, B].map(_.last)
takeLastSuccess: [A, B](seq: Seq[scalaz.Scalaz.ValidationNEL[A,B]])scalaz.Validation[scalaz.NonEmptyList[A],B]
scala> takeLastSuccess(successResults)
res0: scalaz.Validation[scalaz.NonEmptyList[Exception],Int] = Success(42)
scala> takeLastSuccess(failResults)
res1: scalaz.Validation[scalaz.NonEmptyList[Exception],Int] = Failure(NonEmptyList(java.lang.NumberFormatException: For input string: "a", java.lang.NumberFormatException: For input string: "b"))
Related
I have a map of string to IO like this Map[String, IO[String]], I want to transform it into IO[Map[String, String]]. How to do it?
It would be nice to use unorderedTraverse here, but as codenoodle pointed out, it doesn't work because IO is not a commutative applicative. However there is a type that is, and it's called IO.Par. Like the name suggests, its ap combinator won't execute things sequentially but in parallel, so it's commutative – doing a and then b is not the same as doing b and then a, but doing a and b concurrently is the same as doing b and a concurrently.
So you can use unorderedTraverse using a function that doesn't return IO but IO.Par. However the downside to that is that now you need to convert from IO to IO.Par and then back – hardly an improvement.
To solve this problem, I have added the parUnorderedTraverse method in cats 2.0 that will take care of these conversions for you. And because it all happens in parallel it will also be more efficient! There are also parUnorderedSequence, parUnorderedFlatTraverse and parUnorderedFlatSequence.
I should also point out that this works not only for IO but also for everything else with a Parallel instance, such as Either[A, ?] (where A is a CommutativeSemigroup). It should also be possible for List/ZipList, but nobody appears to have bothered to do it yet.
You'll have to be a little careful with this one. Maps in Scala are unordered, so if you try to use cats's sequence like this…
import cats.instances.map._
import cats.effect.IO
import cats.UnorderedTraverse
object Example1 {
type StringMap[V] = Map[String, V]
val m: StringMap[IO[String]] = Map("1" -> IO{println("1"); "1"})
val n: IO[StringMap[String]] = UnorderedTraverse[StringMap].unorderedSequence[IO, String](m)
}
you'll get the following error:
Error: could not find implicit value for evidence parameter of type cats.CommutativeApplicative[cats.effect.IO]
The issue here is that the IO monad is not actually commutative. Here is the definition of commutativity:
map2(u, v)(f) = map2(v, u)(flip(f)) // Commutativity (Scala)
This definition shows that the result is the same even when the effects happen in a different order.
You can make the above code compile by providing an instance of CommutativeApplicative[IO] but that still doesn't make the IO monad commutative. If you run the following code you can see the side effects are not processed in the same order:
import cats.effect.IO
import cats.CommutativeApplicative
object Example2 {
implicit object FakeEvidence extends CommutativeApplicative[IO] {
override def pure[A](x: A): IO[A] = IO(x)
override def ap[A, B](ff: IO[A => B])(fa: IO[A]): IO[B] =
implicitly[Applicative[IO]].ap(ff)(fa)
}
def main(args: Array[String]): Unit = {
def flip[A, B, C](f: (A, B) => C) = (b: B, a: A) => f(a, b)
val fa = IO{println(1); 1}
val fb = IO{println(true); true}
val f = (a: Int, b: Boolean) => s"$a$b"
println(s"IO is not commutative: ${FakeEvidence.map2(fa, fb)(f).unsafeRunSync()} == ${FakeEvidence.map2(fb, fa)(flip(f)).unsafeRunSync()} (look at the side effects above^^)")
}
}
Which outputs the following:
1
true
true
1
IO is not commutative: 1true == 1true (look at the side effects above^^)
In order to get around this I would suggest making your map something with an order, like a List, where sequence will not require commutativity. The following example is just one way to do this:
import cats.effect.IO
import cats.implicits._
object Example3 {
val m: Map[String, IO[String]] = Map("1" -> IO {println("1"); "1"})
val l: IO[List[(String, String)]] = m.toList.traverse[IO, (String, String)] { case (s, io) => io.map(s2 => (s, s2))}
val n: IO[Map[String, String]] = l.map { _.toMap }
}
Assume we have EitherT[F, String, A].
The withFilter function of Scalaz uses the zero of String's Monoid in order to fill in Left if the filter fails.
Therefore, there is no meaningful error message.
How could I implement something of the form where Left would be "Not positive".
val a: Either[Future, String, Int] = -1.point[EitherT[Future, String, ?]]
val foo = for {
aa <- a
if aa >= 0
} yield aa
Are the filter and withFilter methods on EitherT just hacks to fulfill the for-comprehension demands?
You can use EitherT#ensure :
import scalaz._, Scalaz._
val xs: List[String \/ Int] =
List(1.right, 2.right, -5.right, "other error".left, 3.right, -4.right)
EitherT(xs).ensure("not positive")(_ > 0)
// EitherT(List(\/-(1), \/-(2), -\/(not positive), -\/(other error), \/-(3), -\/(not positive)))
I am using scalaz validation, and have some code to validate products.
def validateProduct(product: Option[Product]): ValidationNel[String, Product] = ???
Given a list of products, I want to get a single validation containing the whole list as a successful value or a list of validation errors. It seems like some kind of fold should do it, but I am not sure what the combination function should be.
def validateProducts(products: Seq[Option[Product]]): ValidationNel[String, Seq[Product]] = {
val listOfValidations: Seq[ValidationNel[String, Product]] = products.map(validateProduct _)
val validatedList:ValidationNel[Seq[String], Seq[Product]] = ??? // what to do here?
???
}
Any help is appreciated
If instead of a ValidationNel[List[String], List[Product]] you want a ValidationNel[String, List[Product]] (i.e., all the failures in the same list), you can just use traverse:
val result: ValidationNel[String, List[Product]] =
products.toList.traverseU(validateProduct)
Note that I've converted the Seq to a List as there are no type class instances for raw Seq, and I'm using traverseU rather than traverse as Scala's type inference doesn't quite work for non-trivial type constructors like ValidationNel
You can use fold with applicative
import scalaz.syntax.validation._
import scalaz.syntax.applicative._
case class Product(name: String)
val allGood = Seq(
Product("a").successNel[String],
Product("b").successNel[String]
)
val aggregated: ValidationNel[String, Seq[Product]] =
allGood.foldLeft(Seq.empty[Product].successNel[String]) {
case (acc , v) => (acc |#| v)(_ :+ _)
}
println(aggregated)
My code consists of a number of scala.concurrent.Futures returned from invoking Akka actors
So sample code in my actor would be something like the following:
val ivResult: Future[Any] = ask(ivActor, ivId)
// perform mapping is a function of type (Any) => Unit
val ivMapping: Future[Unit] = ivResult.map(performingMapping)
// erLookup is a function of type (Any) => Future[Any]
val erResult: Future[Any] = ivResult.flatMap(erLookup)
And so on. Code basically consists of future.flatmap().map() to perform aggregation logic
My problem is that I want to implement null-safe logic such that if the result of a future is null then we don't throw NullPointerExceptions
Obviously, I can embed null-safe checks in each of my functions, but these seems a little verbose considering Scala's powerful capabilities.
Therefore, I'm looking to find out if there is a more elegant way to do this, perhaps using implicits etc.
The result of a Future already indicates whether it completed successfully.
Normally, on NPE your code would blow up and the future is failed.
You're saying, Please don't let my code blow up, with possibly deleterious side effects.
So you want a guard with a special failure state.
Something like:
scala> object DeadFuture extends Exception with NoStackTrace
defined object DeadFuture
scala> implicit class SafeFuture[A](val f: Future[A]) {
| def safeMap[B](m: A => B)(implicit x: ExecutionContext) =
| f.map { a: A => if (a == null) throw DeadFuture else m(a) }(x)
| def safeFlatMap[B](m: A => Future[B])(implicit x: ExecutionContext) =
| f.flatMap { a: A => if (a == null) (Future failed DeadFuture) else m(a) }(x)
| }
then
scala> case class Datum(i: Int)
defined class Datum
scala> def f(d: Datum): Int = 2 * d.i
f: (d: Datum)Int
scala> def g(d: Datum): Future[Int] = Future(2 * d.i)
g: (d: Datum)scala.concurrent.Future[Int]
scala> Future[Datum](null) safeMap f
res1: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise#5fa5debb
scala> .value
res3: Option[scala.util.Try[Int]] = Some(Failure(DeadFuture$))
scala> def g(d: Datum): Future[Int] = Future(2 * d.i)
g: (d: Datum)scala.concurrent.Future[Int]
scala> Future[Datum](null) safeFlatMap g
res4: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise#7f188fd
scala> .value
res5: Option[scala.util.Try[Int]] = Some(Failure(DeadFuture$))
There might be a better way to induce the conversion, so you keep for-comprehensions.
for (i <- safely(futureInt)) f(i)
Is there a way in Scala to convert a List[Int] to java.util.List[java.lang.Integer]?
I'm interfacing with Java (Thrift).
JavaConversions supports List --> java.util.List, and implicits exist between Int --> java.lang.Integer, but from what I can tell I would still need an extra pass to manually do the conversion:
val y = List(1)
val z: java.util.List[Integer] = asList(y) map { (x: Int) => x : java.lang.Integer }
Apparently you need both conversions. However, you can group them in a single implicit conversion:
implicit def toIntegerList( lst: List[Int] ) =
seqAsJavaList( lst.map( i => i:java.lang.Integer ) )
Example:
scala> def sizeOf( lst: java.util.List[java.lang.Integer] ) = lst.size
scala> sizeOf( List(1,2,3) )
res5: Int = 3
Because the underlying representation of Int is Integer you can cast directly to java.util.List[java.lang.Integer]. It will save you an O(n) operation and some implicit stuff.
import collection.JavaConversions._
class A {
def l() = asList(List(1,2)).asInstanceOf[java.util.List[java.lang.Integer]]
}
Then you can use from Java like this:
A a = new A();
java.util.List<Integer> l = a.l();
Note that on 2.9.0 ,I get a deprecation warning on asList (use seqAsJavaList instead)
Did you try:
val javalist = collection.JavaConversions.asJavaList (y)
I'm not sure, whether you need a conversion Int=>Integer or Int=>int here. Can you try it out?
Update:
The times, they are a changing. Today you'll get a deprecated warning for that code. Use instead:
import scala.collection.JavaConverters._
val y = List (1)
> y: List[Int] = List(1)
val javalist = (y).asJava
> javalist: java.util.List[Int] = [1]
This doesn't have an implicit at the outmost layer, but I like this generic approach and have implemented it for a couple of types of collections (List, Map).
import java.util.{List => JList}
import scala.collection.JavaConverters._
def scalaList2JavaList[A, B](scalaList: List[A])
(implicit a2bConversion: A => B): JList[B] =
(scalaList map a2bConversion).asJava
Since an implicit conversion from Int to Integer is part of standard lib, usage in this case would just look like this:
scalaList2JavaList[Int, Integer](someScalaList)
In the other direction!
(since I have these available anyway as they were my original implementations...)
import java.util.{List => JList}
import scala.collection.JavaConversions._
def javaList2ScalaList[A, B](javaList: JList[A])
(implicit a2bConversion: A => B): List[B] =
javaList.toList map a2bConversion
Usage:
javaList2ScalaList[Integer, Int](someJavaList)
This can then be re-used for all lists so long as an implicit conversion of the contained type is in scope.
(And in case you're curious, here is my implementation for map...)
def javaMap2ScalaMap[A, B, C, D](javaMap: util.Map[A, B])(implicit a2cConversion: A => C, b2dConversion: B => D): Map[C, D] =
javaMap.toMap map { case (a, b) => (a2cConversion(a), b2dConversion(b)) }
Starting Scala 2.13, the standard library includes scala.jdk.CollectionConverters which provides Scala to Java implicit collection conversions.
Which we can combine with java.lang.Integer::valueOf to convert Scala's Int to Java's Integer:
import scala.jdk.CollectionConverters._
List(1, 2, 3).map(Integer.valueOf).asJava
// java.util.List[Integer] = [1, 2, 3]
I was trying to pass a Map[String, Double] to a Java method. But the problem was JavaConversions converts the Map to a java Map, but leaves the scala Double as is, instead of converting it to java.lang.Double. After a few hours of seaching I found [Alvaro Carrasco's answer])https://stackoverflow.com/a/40683561/1612432), it is as simple as doing:
val scalaMap = // Some Map[String, Double]
val javaMap = scalaMap.mapValues(Double.box)
After this, javaMap is a Map[String, java.lang.Double]. Then you can pass this to a java function that expects a Map<String, Double> and thanks to implicit conversions the Scala Map will be converted to java.util.Map
In your case would be the same, but with Int.box:
val y = List(1)
val javay = y.map(Int.box)