Scalaz validation: convert sequence of validations to a single validation - scala

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)

Related

cats-effect:How to transform Map[x,IO[y]] to IO[Map[x,y]]

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 }
}

Why does a for comprehension expand to a `withFilter`

I'm working on a DSL for relational (SQL-like) operators. I have a Rep[Table] type with an .apply: ((Symbol, ...)) => Obj method that returns an object Obj which defines .flatMap: T1 => T2 and .map: T1 => T3 functions. As the type Rep[Table] does not know anything about the underlying table's schema, the apply method acts like a projection - projecting only the fields specified in the argument tuple (a lot like the untyped scalding api). Now type T1 is a "tuple-like", its length constrained to the projection tuple's length by some shapeless magic, but otherwise the types of the tuple elements are decided by the api user, so code like
val a = loadTable(...)
val res = a(('x, 'y)).map { (t: Row2[Int, Int]) =>
(1, t(0))
}
or
val res = a(('x, 'y)).map { (t: Row2[String, String]) =>
(1, t(0))
}
works fine. Note that the type of the argument for the map/flatMap function must be specified explicitly. However, when I try to use it with a for comprehension
val a = loadTable(...)
val b = loadTable(...)
val c = loadTable(...)
val res = for {
as: Row2[Int, Int] <- a(('ax, 'ay))
bs: Row2[Int, Int] <- b(('bx, 'by))
cs: Row2[Int, Int] <- c(('cx, 'cy))
} yield (as(0), as(1), bs(0), bs(1), cs(0), cs(1))
it complains about the lack of a withFilter operator. Adding an .withFilter: T1 => Boolean does not cut it - it then complains about "missing parameter type for expanded function", as T1 is parameterised by some type. Only adding .withFilter: Row[Int, Int] => Boolean makes it work, but obviously is not what I want at all.
My questions are: why does the withFilter get called in the first place and how can I use it with my parameterised tuple-like type T1?
Edit
In the end I went with a .withFilter: NothingLike => BoolLike which is a noop for simple checks like _.isInstanceOf[T1] and a more restricted .filter: T1 => BoolLike to be used in general case.
Unfortunately, you cannot use for-comprehensions when you expect type inference based on the argument type of your lambda.
Actually, in your example, as: Row2[Int, Int] is interpreted as a pattern match:
val res = for {
as: Row2[Int, Int] <- a(('ax, 'ay))
} yield (...)
Translates to something like:
a(('ax, 'ay)).withFilter(_.isInstanceOf[Row2[Int, Int]]).map(...)
Pattern matching in for comprehensions can be very useful:
val names = for {
("name", name) <- keyValPairs
} yield name
But the trade-off is, that you cannot explicitly specify the argument type of the lambda.
I bumped into this issue also. Thanks to gzm0 explaining the Scala compilers behaviour I came up with this workaround:
import cats._
import cats.data._
import cats.implicits._
object CatsNEL extends App {
val nss: NonEmptyList[(Int, String)] = NonEmptyList.of((1,"a"), (2, "b"), (3, "c"))
val ss: NonEmptyList[String] = for {
tuple <- nss
(n, s) = tuple
} yield s
}

Wrapping a Monad into a parser - do I need Monad Transformers and how to do it?

I have a monadic type Exp and I want to build a parser that parses into such a value. The following code works, but is there something nicer/cooler I can do?
def grid(x: Int, y: Int): Problem = ???
def expInt: Parser[Exp[Int]] = ???
def grid: Parser[Exp[Problem]] =
for{
ex ~ _ ~ ey <- "grid(" ~> expInt ~ "," ~ expInt <~ ")"
} yield for{
x <- ex
y <- ey
} yield grid(x,y)
I've heard of monad transformers, but still are a bit scared of Scalaz 7's wierd import system. Can someone answer whether
I can use monad transformers and
How this would look like in principle, using Scalaz 7 for a Scala combinator parser wrapping my own Exp Monad.
First for the easy part—the "weird" import system:
import scalaz._, Scalaz._
That's all. This will always work (barring name collisions, of course, but that's a possibility with any library and is easy to resolve), and nobody's going to look down on you for not using the new à la carte imports, which are mainly about documentation.
The basic pattern for monad transformers is that you have a WhateverT[F[_], ...] type class that has a method named runWhateverT (or just run) that returns an F[Whatever[...]].
In this case it looks like you want to end up with a Parser[Exp], which suggests that you need your own ExpT[F[_]] transformer. I won't start with details about how to implement this (which will depend on the semantics of your monad, of course), but will give an example using Scalaz's OptionT:
import scala.util.parsing.combinator._
import scalaz._, Scalaz._
object MyParser extends RegexParsers {
implicit val monad = parserMonad(this)
def oddNumber: OptionT[Parser, Int] = OptionT.optionT(
"\\d+".r ^^ (_.toInt) ^^ (i => (i % 2 != 0) option i)
)
def pairOfOdds: OptionT[Parser, (Int, Int)] = for {
_ <- literal("(").liftM[OptionT]
x <- oddNumber
_ <- literal(",").liftM[OptionT]
y <- oddNumber
_ <- literal(")").liftM[OptionT]
} yield (x, y)
def apply(s: String) = parse(pairOfOdds.run, s)
}
See my question here for some discussion about why we need the implicit val monad = ... line.
It works like this:
scala> MyParser("(13, 43)")
res0: MyParser.ParseResult[Option[(Int, Int)]] = [1.9] parsed: Some((13,43))
scala> MyParser("(13, 42)")
res1: MyParser.ParseResult[Option[(Int, Int)]] = [1.8] parsed: None
Note that oddNumber.run would give us a Parser[Option[Int]] that will parse a string of digits and return either a Some(i) (if they represent an odd number) or a None (if they're even).
We're not actually going to call oddNumber.run, though, in this case—the fact that we're using a monad transformer means that we can compose oddNumber with lifted Parser actions (the literal(...) here) in a single for comprehension.
The syntax here is ugly—we lose the nice ~ combinators and the implicit conversions from String to Parser[String], for example, but we could easily write lifted versions of those things if we wanted.

Iterable[Try[(K, V)]] to Try[Map[K, V]]

I have a method load which is relatively expensive to call. In order to allow some kind of exception handling during loading it returns a Try. I need now an implementation for the loadAll method which basically delegates to load for each of the given keys. Here is my first approach, however I don't know if this is best practices with respect to the work with Try. Is there a better way to achieve the following?
def load(key: K): Try[V] // very expensive
def loadAll(keys: Traversable[K]): Try[Map[K, V]] = {
// remove duplicate keys
val ukeys = Set.empty ++ keys
val result: Iterable[Try[(K, V)]] = ukeys map { key =>
load(key) match {
case Success(value) => Success(key, value)
case Failure(exception) => Failure(exception)
}
}
Try(result.map { _.get }.toMap)
}
You can do this using a fold to iterate over the keys, and a for comprehension to combine the Try instances:
def toSet(keys: Traversable[K]): Try[Map[K, V]] = {
keys.toSet.foldLeft( Try( Map.empty[K, V] ) ){ case (tryMap, key) =>
for ( m <- tryMap; v <- load( key ) ) yield m.updated( key, v )
}
}
It's a one-liner in vanilla Scala (assuming you've already got Try in scope):
def loadAll(keys: Traversable[K]) = Try{ keys.toSet.map((k: K) => (k,load(k).get)).toMap }
If you're interested in a scalaz solution, this is a general operation, available via Traversable functors, called sequence. Needed instances for Try reside in scalaz-contrib. Here's how it might look like:
Welcome to Scala version 2.10.1 (OpenJDK 64-Bit Server VM, Java 1.7.0_21).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scalaz._, Scalaz._, scalaz.contrib.std.utilTry._
import scalaz._
import Scalaz._
import scalaz.contrib.std.utilTry._
scala> import scala.util.Try
import scala.util.Try
scala> val result: Iterable[Try[(Int, String)]] = Iterable.empty
result: Iterable[scala.util.Try[(Int, String)]] = List()
scala> result.toList.sequence.map(_.toMap)
res0: scala.util.Try[scala.collection.immutable.Map[Int,String]] = Success(Map())
By the way, there's a paper "The essence of the Iterator pattern", describing/deriving traverse (and sequence, as it's special case). There's a great summary of this paper by Eric Torreborre here.

Accumulating only validation errors in Scalaz

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"))