Chaining Scalaz validation functions: Function1[A,Validation[E,B]] - scala

I'm trying to write some code to make it easy to chain functions that return Scalaz Validation types. One method I am trying to write is analogous to Validation.flatMap (Short circuit that validation) which I will call andPipe. The other is analogous to |#| on ApplicativeBuilder (accumulating errors) except it only returns the final Success type, which I will call andPass
Suppose I have functions:
def allDigits: (String) => ValidationNEL[String, String]
def maxSizeOfTen: (String) => ValidationNEL[String, String]
def toInt: (String) => ValidationNEL[String, Int]
As an example, I would like to first pass the input String to both allDigits and maxSizeOf10. If there are failures, it should short circuit by not calling the toInt function and return either or both failures that occurred. If Successful, I would like to pass the Success value to the toInt function. From there, it would either Succeed with the output value being an Int, or it would fail returning only the validation failure from toInt.
def intInput: (String) => ValidationNEL[String,Int] = (allDigits andPass maxSizeOfTen) andPipe toInt
Is there a way to do this without my add-on implementation below?
Here is my Implementation:
trait ValidationFuncPimp[E,A,B] {
val f: (A) => Validation[E, B]
/** If this validation passes, pass to f2, otherwise fail without accumulating. */
def andPipe[C](f2: (B) => Validation[E,C]): (A) => Validation[E,C] = (a: A) => {
f(a) match {
case Success(x) => f2(x)
case Failure(x) => Failure(x)
}
}
/** Run this validation and the other validation, Success only if both are successful. Fail accumulating errors. */
def andPass[D](f2: (A) => Validation[E,D])(implicit S: Semigroup[E]): (A) => Validation[E,D] = (a:A) => {
(f(a), f2(a)) match {
case (Success(x), Success(y)) => Success(y)
case (Failure(x), Success(y)) => Failure(x)
case (Success(x), Failure(y)) => Failure(y)
case (Failure(x), Failure(y)) => Failure(S.append(x, y))
}
}
}
implicit def toValidationFuncPimp[E,A,B](valFunc : (A) => Validation[E,B]): ValidationFuncPimp[E,A,B] = {
new ValidationFuncPimp[E,A,B] {
val f = valFunc
}
}

I'm not claiming that this answer is necessarily any better than drstevens's, but it takes a slightly different approach and wouldn't fit in a comment there.
First for our validation methods (note that I've changed the type of toInt a bit, for reasons I'll explain below):
import scalaz._, Scalaz._
def allDigits: (String) => ValidationNEL[String, String] =
s => if (s.forall(_.isDigit)) s.successNel else "Not all digits".failNel
def maxSizeOfTen: (String) => ValidationNEL[String, String] =
s => if (s.size <= 10) s.successNel else "Too big".failNel
def toInt(s: String) = try(s.toInt.right) catch {
case _: NumberFormatException => NonEmptyList("Still not an integer").left
}
I'll define a type alias for the sake of convenience:
type ErrorsOr[+A] = NonEmptyList[String] \/ A
Now we've just got a couple of Kleisli arrows:
val validator = Kleisli[ErrorsOr, String, String](
allDigits.flatMap(x => maxSizeOfTen.map(x *> _)) andThen (_.disjunction)
)
val integerizer = Kleisli[ErrorsOr, String, Int](toInt)
Which we can compose:
val together = validator >>> integerizer
And use like this:
scala> together("aaa")
res0: ErrorsOr[Int] = -\/(NonEmptyList(Not all digits))
scala> together("12345678900")
res1: ErrorsOr[Int] = -\/(NonEmptyList(Too big))
scala> together("12345678900a")
res2: ErrorsOr[Int] = -\/(NonEmptyList(Not all digits, Too big))
scala> together("123456789")
res3: ErrorsOr[Int] = \/-(123456789)
Using flatMap on something that isn't monadic makes me a little uncomfortable, and combining our two ValidationNEL methods into a Kleisli arrow in the \/ monad—which also serves as an appropriate model for our string-to-integer conversion—feels a little cleaner to me.

This is relatively concise with little "added code". It is still sort of wonky though because it ignores the successful result of applying allDigits.
scala> val validated = for {
| x <- allDigits
| y <- maxSizeOfTen
| } yield x *> y
validated: String => scalaz.Validation[scalaz.NonEmptyList[String],String] = <function1>
scala> val validatedToInt = (str: String) => validated(str) flatMap(toInt)
validatedToInt: String => scalaz.Validation[scalaz.NonEmptyList[String],Int] = <function1>
scala> validatedToInt("10")
res25: scalaz.Validation[scalaz.NonEmptyList[String],Int] = Success(10)
Alternatively you could keep both of the outputs of allDigits and maxSizeOfTen.
val validated2 = for {
x <- allDigits
y <- maxSizeOfTen
} yield x <|*|> y
I'm curious if someone else could come up with a better way to combine these. It's not really composition...
val validatedToInt = (str: String) => validated2(str) flatMap(_ => toInt(str))
Both validated and validated2 accumulate failures as shown below:
scala> def allDigits: (String) => ValidationNEL[String, String] = _ => failure(NonEmptyList("All Digits Fail"))
allDigits: String => scalaz.Scalaz.ValidationNEL[String,String]
scala> def maxSizeOfTen: (String) => ValidationNEL[String, String] = _ => failure(NonEmptyList("max > 10"))
maxSizeOfTen: String => scalaz.Scalaz.ValidationNEL[String,String]
scala> val validated = for {
| x <- allDigits
| y <- maxSizeOfTen
| } yield x *> y
validated: String => scalaz.Validation[scalaz.NonEmptyList[String],String] = <function1>
scala> val validated2 = for {
| x <- allDigits
| y <- maxSizeOfTen
| } yield x <|*|> y
validated2: String => scalaz.Validation[scalaz.NonEmptyList[String],(String, String)] = <function1>
scala> validated("ten")
res1: scalaz.Validation[scalaz.NonEmptyList[String],String] = Failure(NonEmptyList(All Digits Fail, max > 10))
scala> validated2("ten")
res3: scalaz.Validation[scalaz.NonEmptyList[String],(String, String)] = Failure(NonEmptyList(All Digits Fail, max > 10))

Use ApplicativeBuilder with the first two, so that the errors accumulate,
then flatMap toInt, so toInt only gets called if the first two succeed.
val validInt: String => ValidationNEL[String, Int] =
for {
validStr <- (allDigits |#| maxSizeOfTen)((x,_) => x);
i <- toInt
} yield(i)

Related

Extract Value from nested options

What is the most concise way to get 10 out of Some(Some(Some(Some(10))))?
without resorting to some external library like Scalaz.
import scala.language.higherKinds
case class Flattener[W[_], WW, T](fn : WW => W[T])
implicit def optionRecFlattenFn[WW, T](
implicit f : Flattener[Option, WW, T] = Flattener((ww: WW) => Option(ww))
) = Flattener((ww : Option[WW]) => ww.flatMap(f.fn))
def optionRecursiveFlatten[WW, T](www : Option[WW])(
implicit f : Flattener[Option, Option[WW], T]
) = f.fn(www)
val nestedOption = Option(Option(Option(Option(10))))
// Some(Some(Some(Some(10))))
val flatOption = optionRecursiveFlatten(nestedOption)
// Some(10)
val evenMoreNestedOption = Option(Option(Option(Option(Option(Option(10))))))
// Some(Some(Some(Some(Some(Some(10))))))
val flatOption2 = optionRecursiveFlatten(evenMoreNestedOption)
// Some(10)
In case you don't know the nesting level in advance, this will work for any level:
def unwrapRec(o: Option[Any]) : Any = o match {
case Some(inner # Some(_)) => unwrapRec(inner)
case Some(x) => x
case _ => ???
}
However, please note that an Any is returned. You can change it to whatever type you like and adapt the pattern match accordingly but I think you will have to pass in an Option[Any]. So it's not typesafe at this point.
You can use flatten on nested Option[Option[A]] repeatedly:
scala> val a = Some(Some(Some(Some(10))))
a: Some[Some[Some[Some[Int]]]] = Some(Some(Some(Some(10))))
scala> a.flatten.flatten.flatten.get
res0: Int = 10
I do not think there is any generic and type-safe way to extract A from T[A] := Option[T[A]] | A.
Edit: This method can dynamically get the contents, returns either the innermost value, or None:
def unwrap(x: Any): Any = x match {
case Some(v) => unwrap(v)
case v => v
}
scala> unwrap(Some(Some(Some(Some(10)))))
res1: Any = 10
scala> unwrap(Some(None))
res2: Any = None
It has unfortunately too broad type: Any => Any.

Apply several transformation functions to string

Suppose I have 2 methods:
def a(s: String) = s + "..."
def b(s: String) = s + ",,,"
And I want to create 3rd method which will call both methods:
def c (s: String) = a(b(s))
How I can do it in idiomatic Scala way?
I think it's better to aggregate this functions into some List and then sequentially apply them:
List(a_, b_)
I think it's better to aggregate this functions into some List and
then sequentially apply them.
You get some help by specifying an expected type:
scala> val fs: List[String => String] = List(a,b)
fs: List[String => String] = List(<function1>, <function1>)
scala> fs.foldLeft("something")((s,f) => f(s))
res0: String = something...,,,
Here is how you can combine a set of functions into one:
// a() and b() are as defined in the question
// the following is equivalent to newfunc(x) = b(a(x))
val newFunc: String => String = List( a _, b _).reduce( _ andThen _ )
You can even create a generic function to combine them:
def functionChaining[A]( functions: A => A *): A => A = functions.reduce( _ andThen _ )
or using foldLeft:
def functionChaining[A]( functions: A => A *): A => A = functions.foldLeft( (x:A) => x )( _ andThen _ )
Here is an example of how to use this on the REPL:
scala> val newFunc: String => String = functionChaining( (x:String) => x + "---", (x:String) => x * 4)
scala> newFunc("|")
res12: String = |---|---|---|---
Many answers use andThen, but that will be give you
b(a(s))
Given that you want
a(b(s))
compose is the way to go (well, that or reversing the list, but what's the point?)
def c(s: String) = List[String => String](a, b).reduce(_ compose _)(s)
// or alternatively
def c(s: String) = List(a _, b _).reduce(_ compose _)(s)
As a result
c("foo") // foo,,,...
Now, speaking of what's idiomatic, I believe that
a(b(s))
is more idiomatic and readable than
List(a _, b _).reduce(_ compose _)(s)
This clearly depends on the number of functions you're composing. If you were to have
a(b(c(d(e(f(g(h(s))))))))
then
List[String => String](a, b, c, d, e, f, g, h).reduce(_ compose _)(s)
is probably neater and more idiomatic as well.
If you really think you need to do this:
val c = a _ andThen b
// (The signature is:)
val c:(String)=>String = a _ andThen b
or, more obviously:
def d(s:String) = a _ andThen b
If chained application is preferred then the below works. Caveats - Implicit syntax is a bit ugly; This being a structural type uses reflection.
object string {
implicit def aPimp(s: String) = new {
def a = "(a- " + s + " -a)"
}
implicit def bPimp(s: String) = new {
def b = "(b- " + s + " -b)"
}
}
scala> import string._
scala> "xyz".a.b
res0: String = (b- (a- xyz -a) -b)
scala> "xyz".b.a
res1: String = (a- (b- xyz -b) -a)
In my opinion, if not for the ugly syntax, this would be idiomatic scala.

Converting multiple optional values in Scala

I am writing a function that receives several optional String values and converts each one to either an Int or a Boolean and then passes the converted values to Unit functions for further processing. If any conversion fails, the entire function should fail with an error. If all conversions succeed, the function should process the converted values and return a success.
Here is the function I have written (simplified from the actual):
f(x: Option[String], y: Option[String], z: Option[String]): Result = {
val convertX = x.map(value => Try(value.toInt))
val convertY = y.map(value => Try(value.toBoolean))
val convertZ = z.map(value => Try(value.toBoolean))
val failuresExist =
List(convertX, convertY, convertZ).flatten.exists(_.isFailure)
if (failuresExist) BadRequest("Cannot convert input")
else {
convertX.foreach {
case Success(value) => processX(value)
case _ =>
}
convertY.foreach {
case Success(value) => processY(value)
case _ =>
}
convertZ.foreach {
case Success(value) => processZ(value)
case _ =>
}
Ok()
}
}
Although this solution will probably work, it is very awkward. How can I improve it?
A more imperative style could work, if you don't mind that.
def f(x: Option[String], y: Option[String], z: Option[String]): Result = {
try {
val convertX = x.map(_.toInt)
val convertY = y.map(_.toBoolean)
val convertZ = z.map(_.toBoolean)
convertX.foreach(processX)
convertY.foreach(processY)
convertZ.foreach(processZ)
Ok()
} catch {
case _: IllegalArgumentException | _: NumberFormatException => BadRequest("Cannot convert input")
}
}
If you're using scalaz I would use the Option applicative and ApplicativeBuilder's |#| combinator. If any of the inputs are None, then the result is also None.
import scalaz.std.option.optionInstance
import scalaz.syntax.apply._
val result: Option[String] =
Some(1) |#| Some("a") |#| Some(true) apply {
(int, str, bool) =>
s"int is $int, str is $str, bool is $bool"
}
In pure scala, you could use flatMap on option:
val result: Option[String] =
for {
a <- aOpt
b <- bOpt
c <- cOpt
} yield s"$a $b $c"
I personally prefer the applicative because it makes it clear that the results are independent. for-blocks read to me like "first do this with a, then this with b, then this with c" whereas applicative style is more like "with all of a, b, and c, do ..."
Another option with scalaz is sequence, which inverts a structure like T[A[X]] into A[T[X]] for traversable T and applicative A.
import scalaz.std.option.optionInstance
import scalaz.std.list.listInstance
import scalaz.syntax.traverse._
val list: List[Option[Int]] = List(Option(1), Option(4), Option(5))
val result: Option[List[Int]] = list.sequence
// Some(List(1, 4, 5))
For completence I am adding the a piece of code here that process the values are required. However if this is better than that the original is debatable. If you want to process all the value and gather the results of the transformation scalaz Validator could be a better option.
import scala.util.Try
val x = Some("12")
val y = Some("false")
val z = Some("hello")
def process(v: Boolean) = println(s"got a $v")
def processx(v: Int) = println(s"got a number $v")
// Abstract the conversion to the appropriate mapping
def mapper[A, B](v: Option[String])(mapping: String => A)(func: Try[A] => B) = for {
cx <- v.map(vv => Try(mapping(vv)))
} yield func(cx)
def f(x: Option[String], y: Option[String], z: Option[String]) = {
//partially apply the function here. We will use that method twice.
def cx[B] = mapper[Int, B](x)(_.toInt) _
def cy[B] = mapper[Boolean, B](y)(_.toBoolean) _
def cz[B] = mapper[Boolean, B](z)(_.toBoolean) _
//if one of the values is a failure then return the BadRequest,
// else process each value and return ok
(for {
vx <- cx(_.isFailure)
vy <- cy(_.isFailure)
vz <- cz(_.isFailure)
if vx || vy || vz
} yield {
"BadRequest Cannot convert input"
}) getOrElse {
cx(_.map(processx))
cy(_.map(process))
cz(_.map(process))
"OK"
}
}
f(x,y,z)
In the case a "short circuit" behaviour is required the following code will work.
import scala.util.Try
val x = Some("12")
val y = Some("false")
val z = Some("hello")
def process(v: Boolean) = println(s"got a $v")
def processx(v: Int) = println(s"got a number $v")
def f(x: Option[String], y: Option[String], z: Option[String]) =
(for {
cx <- x.map(v => Try(v.toInt))
cy <- y.map(v => Try(v.toBoolean))
cz <- z.map(v => Try(v.toBoolean))
} yield {
val lst = List(cx, cy, cz)
lst.exists(_.isFailure) match {
case true => "BadRequest Cannot convert input"
case _ =>
cx.map(processx)
cy.map(process)
cz.map(process)
"OK"
}
}) getOrElse "Bad Request: missing values"
f(x,y,z)

Apply a list of parameters to a list of functions

I have a list of parameters like List(1,2,3,"abc","c") and a set of functions which validates the data present in the list like isNumberEven, isAValidString etc.
Currently, I take each value of the list and apply proper function which validates the data like isNumberEven(params(0)). This has led to big and messy code which is completely imperative in thinking.
I am expecting that it should be possible to do something like this in Scala -
List(1,2,3,"abc","c").zip(List(fuctions)).foreach{ x => x._2(x._1)}
However, this fails giving a runtime exception of type mismatch:
error: type mismatch;
found : x._1.type (with underlying type Any)
required: Int with String
I tried pattern matching on Function traits but it fails due to type erasure.
Any pointers will be appreciated as how can this be solved.
Very naive and non extensible implementation, I'm not very good with types, surely there's a better way:
val c = List(1,2,3,"abc","c")
def isEven(x: Int) = if(x % 2 == 0) true else false
def isUpperCase(x: String) = if(x.head.isUpper) true else false
c.map {
case x: Int => isEven(x)
case x: String => isUpperCase(x)
case _ => false
}
You could also define list of functions:
scala> val c = List(1,2,3,"abc","c")
c: List[Any] = List(1, 2, 3, abc, c)
scala> def isEven(x: Int) = if(x % 2 == 0) true else false
isEven: (x: Int)Boolean
scala> def isOdd(x: Int) = !isEven(x)
isOdd: (x: Int)Boolean
scala> def isUpperCase(x: String) = if(x.head.isUpper) true else false
isUpperCase: (x: String)Boolean
scala> def someString(x: String) = true
someString: (x: String)Boolean
scala> val ints = List(isEven(_), isOdd(_))
ints: List[Int => Boolean] = List(<function1>, <function1>)
scala> val strings = List(isUpperCase(_), someString(_))
strings: List[String => Boolean] = List(<function1>, <function1>)
scala> c.map {
| case x: Int => ints.map(f => f(x)).exists(f => f(x))
| case x: String => strings.map(f => f(x)).forall(f => f(x))
| case _ => false
| }
res2: List[Boolean] = List(true, true, true, false, false)
I just want to present a different approach without matching, although it is certainly sledgehammer-like.
First all functions are converted to functions of type Any => Boolean.
It iterates over the values in c. For each element it tries to find a function that is applicable and that results in true. If it doesn't find one, false is yielded.
def isEven(i: Int) = i % 2 == 0
def isGreaterThanTwo(i: Int) = i > 2
def hasB(s: String) = s.exists(_ == 'b')
def convert[T](func: T => Boolean) = (a: Any) => func(a.asInstanceOf[T])
val functions = List(isEven _, isGreaterThanTwo _, hasB _)
val c = List(1,2,3,"abc","c")
val result = {
val convertedFunctions = functions.map(convert)
c.map(elem => convertedFunctions.exists(func => Try(func(elem)) getOrElse false))
}
with the result List(false, true, true, true, false).
The upside is that you can have as many functions as you like and it is therefore extensible. The downside is that you rely on exceptions. (which is usually not a good practice)
I first tried a solution with converting to PartialFunction and modifying the isDefined methods so it can be called on Any but then checks for a certain type. Then a lot of type-erasure happened and I couldn't make it work. Maybe that could be worth a shot.
If that is possible the code could be changed to:
def convert[T](func: T => Boolean) = new PartialFunction[Any, Boolean] {
def isDefinedAt(x : Any) = ??? //check if x is an instance of T, type erasure problem
def apply(x : Any) = func(x.asInstanceOf[T])
}
val result = {
val convertedFunctions = functions.map(convert)
c.map(elem => convertedFunctions.exists(func =>
func.isDefinedAt(elem) && func(elem)))
}
which looks pretty nice.
I'm not entirely certain on how you're planning on using the data afterwards, because 'foreach' would not actually return anything. But maybe this pattern-matched solution can help you achieve what you want?
scala> val f1 = (x:Int) => false
f1: Int => Boolean = <function1>
scala> val f2 = (x:String) => true
f2: String => Boolean = <function1>
scala> List(1,2,3,"abc","c").map {
case x:String => f2(x)
case x:Int => f1(x)
}
res3: List[Boolean] = List(false, false, false, true, true)

Using lazy evaluation functions in varargs

What is wrong is the following method?
def someMethod(funcs: => Option[String]*) = {
...
}
That actually "works" under 2.7.7 if you add parens:
scala> def someMethod(funcs: => (Option[String]*)) = funcs
someMethod: (=> Option[String]*)Option[String]*
except it doesn't actually work at runtime:
scala> someMethod(Some("Fish"),None)
scala.MatchError: Some(Fish)
at scala.runtime.ScalaRunTime$.boxArray(ScalaRunTime.scala:136)
at .someMethod(<console>:4)
at .<init>(<console>:6)
at .<clinit>(<console>) ...
In 2.8 it refuses to let you specify X* as the output of any function or by-name parameter, even though you can specify it as an input (this is r21230, post-Beta 1):
scala> var f: (Option[Int]*) => Int = _
f: (Option[Int]*) => Int = null
scala> var f: (Option[Int]*) => (Option[Int]*) = _
<console>:1: error: no * parameter type allowed here
var f: (Option[Int]*) => (Option[Int]*) = _
But if you try to convert from a method, it works:
scala> def m(oi: Option[Int]*) = oi
m: (oi: Option[Int]*)Option[Int]*
scala> var f = (m _)
f: (Option[Int]*) => Option[Int]* = <function1>
scala> f(Some(1),None)
res0: Option[Int]* = WrappedArray(Some(1), None)
So it's not entirely consistent.
In any case, you can possibly achieve what you want by passing in an Array and then sending that array to something that takes repeated arguments:
scala> def aMethod(os: Option[String]*) { os.foreach(println) }
aMethod: (os: Option[String]*)Unit
scala> def someMethod(funcs: => Array[Option[String]]) { aMethod(funcs:_*) }
someMethod: (funcs: => Array[Option[String]])Unit
scala> someMethod(Array(Some("Hello"),Some("there"),None))
Some(Hello)
Some(there)
None
If you really want to (easily) pass a bunch of lazily evaluated arguments, then you need a little bit of infrastructure that as far as I know doesn't nicely exist in the library (this is code for 2.8; view it as inspiration for a similar strategy in 2.7):
class Lazy[+T](t: () => T, lt: Lazy[T]) {
val params: List[() => T] = (if (lt eq null) Nil else t :: lt.params)
def ~[S >: T](s: => S) = new Lazy[S](s _,this)
}
object Lz extends Lazy[Nothing](null,null) {
implicit def lazy2params[T : Manifest](lz: Lazy[T]) = lz.params.reverse.toArray
}
Now you can easily create a bunch of parameters that are lazily evaluated:
scala> import Lz._ // To get implicit def
import Lz._
scala> def lazyAdder(ff: Array[()=>Int]) = {
| println("I'm adding now!");
| (0 /: ff){(n,f) => n+f()}
| }
lazyAdder: (ff: Array[() => Int])Int
scala> def yelp = { println("You evaluated me!"); 5 }
yelp: Int
scala> val a = 3
a: Int = 3
scala> var b = 7
b: Int = 7
scala> lazyAdder( Lz ~ yelp ~ (a+b) )
I'm adding now!
You evaluated me!
res0: Int = 15
scala> val plist = Lz ~ yelp ~ (a+b)
plist: Lazy[Int] = Lazy#1ee1775
scala> b = 1
b: Int = 1
scala> lazyAdder(plist)
I'm adding now!
You evaluated me!
res1: Int = 9
Evidently repeated arguments are not available for by-name parameters.