Scalaz check, internal value check

I have a Validation object

val v = Validation[String, Option[Int]] 

I need to do a second check to check if the actual Integer value is really 100. If I do

 val vv = v.map(_.map(intValue => if (intValue == 100) intValue.success[String] else "Bad value found".fail[Integer])) 

I get:

 Validation[String, Option[Validation[String, Int]]] 

How can I get vv as well as Validation [String, Option [Int]] in the most concise way

==========

Found solution from my own:

 val validation: Validation[String, Option[Int]] = Some(100).success[String] val validatedTwice: Validation[String, Option[Int]] = validation.fold( _ => validation, // if Failure then return it _.map(validateValue _) getOrElse validation // validate Successful result ) def validateValue(value: Int): Validation[String, Option[Int]] = { if (value == 100) Some(value).success[String] else "Bad value".fail[Option[Int]] } 

It does not look concise and elegant, although it works

===============

The second solution is from my own, but also looks complicated:

 val validatedTwice2: Validation[String, Option[Int]] = validation.flatMap( _.map(validateValue _).map(_.map(Some(_))) getOrElse validation) def validateValue(value: Int): Validation[String, Int] = { if (value == 100) value.success[String] else "Bad value".fail[Int] } 
+4
source share
3 answers

Your decision is too complicated. The following is enough:

 v flatMap (_.filter(_ == 100).toSuccess("Bad value found")) 

toSuccess derived from OptionW and converts Option[A] to Validation[X, A] , taking the value provided for the failure if the option is empty. flatMap works as follows:

 Validation[X, A] => (A => Validation[X, B]) => (via flatMap) Validation[X, B] 

That is, flatMap displays and then aligns ( join in scalaz-parlance):

 Validation[X, A] => (A => Validation[X, B]] => (via map) Validation[X, Validation[X, B]] => (via join) Validation[X, B] 
+2
source

First, let me set up some type aliases because repeating this set repeatedly will become pretty fast. We will remove your verification logic a little while we are here.

 type V[X] = Validation[String, X] type O[X] = Option[X] def checkInt(i: Int): V[Int] = Validation.fromEither(i != 100 either "Bad value found" or i) val v: V[O[Int]] = _ 

this is where we start - b1 is equivalent to your vv situation

 val b1: V[O[V[Int]]] = v.map(_.map(checkInt)) 

so move the option to flip V [O [V [Int]]] to V [V [O [Int]]]

 val b2: V[V[O[Int]]] = v.map(_.map(checkInt)).map(_.sequence[V, Int]) 

or if you feel lambda, it could be

 sequence[({type l[x] = Validation[String, x]})#l, Int] 

Then we smooth out this nested check - we are going to attract the monad of check, because in fact we really want fastfail behavior, although this is usually not the case.

 implicit val monad = Validation.validationMonad[String] val b3: V[O[Int]] = v.map(_.map(checkInt)).map(_.sequence[V, Int]).join 

So now we have Validation [String, Option [Int]], so we are there, but it is still pretty dirty. Let's use some equatorial reasoning to tidy it up.

According to the second law of the functor, we know that:

 X.map(_.f).map(_.g) = X.map(_.fg) => val i1: V[O[Int]] = v.map(_.map(checkInt).sequence[V, Int]).join 

and by definition of a monad:

 X.map(f).join = X.flatMap(f) => val i2: V[O[Int]] = v.flatMap(_.map(checkInt).sequence[V, Int]) 

and then apply the free traversal theorem:
(I struggled so much with this bloody paper, but it looks like part of it has sunk!):

 X.map(f).sequence = X.traverse(f andThen identity) = X.traverse(f) => val i3: V[O[Int]] = v.flatMap(_.traverse[V, Int](checkInt)) 

So now we are looking at something more civilized. I suppose there is some kind of deception there that needs to be played with a flat mast and traverse, but my inspiration will run out.

+2
source

Use flatMap , for example:

 v.flatMap(_.parseInt.fail.map(_.getMessage).validation) 
0
source

Source: https://habr.com/ru/post/1395071/


All Articles