Scala polymorphic function for filtering an input List of Either - scala

Seeking a more elegant solution
I have this piece of code, I just use it in test cases where it isn't necessary to do any error handling. What it does is:
take an input list of strings
parse them using the DSJSonmapper.parseDSResult method
filters them and extracts the Right value from each Either (Left is an Exception)
The code is as follows:
def parseDs(ins: List[String]) = {
def filterResults[U, T](in: List[Either[U, T]]): List[T] = {
in.filter(y => y.isRight).map(z => z.right.get)
}
filterResults(ins.map(x => DSJsonMapper.parseDSResult(x)))
}
Now, I haven't done an awful lot of polymorphic functions, but this works. However I feel like it's a bit ugly. Has anyone got a better suggestion, how to accomplish the same thing.
I'm aware this is going to come down to a case of personal preference. But suggestions are welcome.

collect is made for exactly this kind of situation:
def filterMe[U,T](in: List[Either[U,T]]): List[T] = in.collect{
case Right(r) => r
}
In fact, it's so good at this you may want to skip the def and just
ins.map(DSJsonMapper.parseDsResult).collect{ case Right(r) => r }

Rex's answer is possibly a little clearer, but here's a slightly shorter alternative that parses and "filters" in a single step:
ins.flatMap(DSJsonMapper.parseDSResult(_).right.toOption)
Here we take the right projection of each parse result and turn that into an Option (which will be None if the parse failed and Some(whatever) otherwise). Since we're using flatMap, the Nones don't appear in the result and the values are pulled out of the Somes.

Related

How can I convert a list of Either to a list of Right values?

I do some data conversion on a list of string and I get a list of Either where Left represents an error and Right represents a successfully converted item.
val results: Seq[Either[String, T]] = ...
I partition my results with:
val (errors, items) = results.partition(_.isLeft)
After doing some error processing I want to return a Seq[T] of valid items. That means, returning the value of all Right elements. Because of the partitioning I already knew that all elements of items Right. I have come up with five possibilities of how to do it. But what is the best in readability and performance? Is there an idiomatic way of how to do it in Scala?
// which variant is most scala like and still understandable?
items.map(_.right.get)
items.map(_.right.getOrElse(null))
items.map(_.asInstanceOf[Right[String, T]].value)
items.flatMap(_.toOption)
items.collect{case Right(item) => item}
Using .get is considered "code smell": it will work in this case, but makes the reader of the code pause and spend a few extra "cycles" in order to "prove" that it is ok. It is better to avoid using things like .get on Either and Option or .apply on a Map or a IndexedSeq.
.getOrElse is ok ... but null is not something you often see in scala code. Again, makes the reader stop and think "why is this here? what will happen if it ends up returning null?" etc. Better to avoid as well.
.asInstanceOf is ... just bad. It breaks type safety, and is just ... not scala.
That leaves .flatMap(_.toOption) or .collect. Both are fine. I would personally prefer the latter as it is a bit more explicit (and does not make the reader stop to remember which way Either is biased).
You could also use foldRight to do both partition and extract in one "go":
val (errors, items) = results.foldRight[(List[String], List[T])](Nil,Nil) {
case (Left(error), (e, i)) => (error :: e, i)
case ((Right(result), (e, i)) => (e, result :: i)
}
Starting in Scala 2.13, you'll probably prefer partitionMap to partition.
It partitions elements based on a function which returns either Right or Left. Which in your case, is simply the identity:
val (lefts, rights) = List(Right(1), Left("2"), Left("3")).partitionMap(identity)
// val lefts: List[String] = List(2, 3)
// val rights: List[Int] = List(1)
which let you use lefts and rights independently and with the right types.
Going through them one by one:
items.map(_.right.get)
You already know that these are all Rights. This will be absolutely fine.
items.map(_.right.getOrElse(null))
The .getOrElse is unnecessary here as you already know it should never happen. I would recommend throwing an exception if you find a Left (somehow) though, something like this: items.map(x => x.right.getOrElse(throw new Exception(s"Unexpected Left: [$x]")) (or whatever exception you think is suitable), rather than meddling with null values.
items.map(_.asInstanceOf[Right[String, T]].value)
This is unnecessarily complicated. I also can't get this to compile, but I may be doing something wrong. Either way there's no need to use asInstanceOf here.
items.flatMap(_.toOption)
I also can't get this to compile. items.flatMap(_.right.toOption) compiles for me, but at that point it'll always be a Some and you'll still have to .get it.
items.collect{case Right(item) => item}
This is another case of "it works but why be so complicated?". It also isn't exhaustive in the case of a Left item being there, but this should never happen so there's no need to use .collect.
Another way you could get the right values out is with pattern matching:
items.map {
case Right(value) => value
case other => throw new Exception(s"Unexpected Left: $other")
}
But again, this is probably unnecessary as you already know that all values will be Right.
If you are going to partition results like this, I recommend the first option, items.map(_.right.get). Any other options either have unreachable code (code you'd never be able to hit through Unit tests or real-life operation) or are unnecessarily complicated for the sake of "looking functional".

Convert try to option without losing error information in Scala

Introduction
I had created a lovely one-liner:
Option("something").map(_ => Try("something else")).flatten.getOrElse("default")
which actually does not compile, with error:
Error:(15, 31) Cannot prove that scala.util.Try[String] <:< Option[B].
Option("").map(_ => Try("")).flatten.getOrElse("");}
^
so I had found a way around:
Option("something").flatMap(_ => Try("something else").toOption).getOrElse("default")
But, the problem
My colleague warned me, that my construction is actually loosing the error information. This is true, and in real-life application - not acceptable.
After getting rid of all the repetition I had ended up with:
implicit class CoolTry[T](t: Try[T]) extends StrictLogging {
def toOptionSE: Option[T] = t match {
case Success(s) => Some(s)
case Failure(ex) =>
logger.error(ex.getMessage, ex)
None
}
}
using:
Option("something").flatMap(_ => Try(new Exception("error")).toOptionSE).getOrElse("default")
Question
I believe there are many similar cases in every application and I simply do not know if either my approach is bad or Try().toOption is simply done wrong?
I understand that logging is a side effect, but while using Try I guess everyone does expect it if something goes wrong?
Can the implicit class be improved?
Is there any utility library handling Try().toOption my way?
Or what (other) approach should I take here?
Thanks!
Forcing logging every time you change a Try[T] to an Option[T] is an undesired effect IMO. When you do such a transformation you're explicitly admitting that you don't really care about the internals of the failure, if it happened. All you want is to access the result, if it exists. Most of the time you say "well, this is undesirable, I always want to log exceptions", but sometimes you simply only care about the end result, so dealing with an Option[T] can be good enough.
Or what (other) approach should I take here?
Using Either[A, B] is an option here, especially in Scala 2.12 when it became right biased. You can simply map over it and only at the end check if there was an error and then log (created with Scala 2.12.1):
val res: Either[Throwable, String] = Option("something")
.map(_ => Try("something else").toEither)
.getOrElse(Right("default"))
.map(str => s"I got my awesome $str")
Ideally (IMO) deferring the logging side effect to the last possible point would serve you better.
One possible improvement would be to make it crystal clear to the user of what is going on; between the implicit being injected somewhere by the compiler and the apparently "pure" name (toOptionSE) it may not be evident of what is going on for a second developer reading and/or modifying your code. Furthermore, you're fixing how you treat the error case and don't leave the opportunity to handle it differently from logging it.
You can treat errors by leveraging projection, like the failed projection defined over Try. If you really want to do this fluently and on one line, you can leverage implicit classes like this.
implicit class TryErrorHandlingForwarding[A](t: Try[A]) {
def onError(handler: Throwable => Unit): Try[A] = {
t.failed.foreach(handler)
t
}
}
// maybe here you want to have an actual logger
def printStackTrace: Throwable => Unit =
_.printStackTrace
Option("something").
flatMap(_ => Try(???).onError(printStackTrace).toOption).
getOrElse("default")
Also, here I'm assuming that for whatever reason you cannot use Try right from the start (as it's been suggested in a comment).

Why do we need flatMap (in general)?

I have been looking into FP languages (off and on) for some time and have played with Scala, Haskell, F#, and some others. I like what I see and understand some of the fundamental concepts of FP (with absolutely no background in Category Theory - so don't talk Math, please).
So, given a type M[A] we have map which takes a function A=>B and returns a M[B]. But we also have flatMap which takes a function A=>M[B] and returns a M[B]. We also have flatten which takes a M[M[A]] and returns a M[A].
In addition, many of the sources I have read describe flatMap as map followed by flatten.
So, given that flatMap seems to be equivalent to flatten compose map, what is its purpose? Please don't say it is to support 'for comprehensions' as this question really isn't Scala-specific. And I am less concerned with the syntactic sugar than I am in the concept behind it. The same question arises with Haskell's bind operator (>>=). I believe they both are related to some Category Theory concept but I don't speak that language.
I have watched Brian Beckman's great video Don't Fear the Monad more than once and I think I see that flatMap is the monadic composition operator but I have never really seen it used the way he describes this operator. Does it perform this function? If so, how do I map that concept to flatMap?
BTW, I had a long writeup on this question with lots of listings showing experiments I ran trying to get to the bottom of the meaning of flatMap and then ran into this question which answered some of my questions. Sometimes I hate Scala implicits. They can really muddy the waters. :)
FlatMap, known as "bind" in some other languages, is as you said yourself for function composition.
Imagine for a moment that you have some functions like these:
def foo(x: Int): Option[Int] = Some(x + 2)
def bar(x: Int): Option[Int] = Some(x * 3)
The functions work great, calling foo(3) returns Some(5), and calling bar(3) returns Some(9), and we're all happy.
But now you've run into the situation that requires you to do the operation more than once.
foo(3).map(x => foo(x)) // or just foo(3).map(foo) for short
Job done, right?
Except not really. The output of the expression above is Some(Some(7)), not Some(7), and if you now want to chain another map on the end you can't because foo and bar take an Int, and not an Option[Int].
Enter flatMap
foo(3).flatMap(foo)
Will return Some(7), and
foo(3).flatMap(foo).flatMap(bar)
Returns Some(15).
This is great! Using flatMap lets you chain functions of the shape A => M[B] to oblivion (in the previous example A and B are Int, and M is Option).
More technically speaking; flatMap and bind have the signature M[A] => (A => M[B]) => M[B], meaning they take a "wrapped" value, such as Some(3), Right('foo), or List(1,2,3) and shove it through a function that would normally take an unwrapped value, such as the aforementioned foo and bar. It does this by first "unwrapping" the value, and then passing it through the function.
I've seen the box analogy being used for this, so observe my expertly drawn MSPaint illustration:
This unwrapping and re-wrapping behavior means that if I were to introduce a third function that doesn't return an Option[Int] and tried to flatMap it to the sequence, it wouldn't work because flatMap expects you to return a monad (in this case an Option)
def baz(x: Int): String = x + " is a number"
foo(3).flatMap(foo).flatMap(bar).flatMap(baz) // <<< ERROR
To get around this, if your function doesn't return a monad, you'd just have to use the regular map function
foo(3).flatMap(foo).flatMap(bar).map(baz)
Which would then return Some("15 is a number")
It's the same reason you provide more than one way to do anything: it's a common enough operation that you may want to wrap it.
You could ask the opposite question: why have map and flatten when you already have flatMap and a way to store a single element inside your collection? That is,
x map f
x filter p
can be replaced by
x flatMap ( xi => x.take(0) :+ f(xi) )
x flatMap ( xi => if (p(xi)) x.take(0) :+ xi else x.take(0) )
so why bother with map and filter?
In fact, there are various minimal sets of operations you need to reconstruct many of the others (flatMap is a good choice because of its flexibility).
Pragmatically, it's better to have the tool you need. Same reason why there are non-adjustable wrenches.
The simplest reason is to compose an output set where each entry in the input set may produce more than one (or zero!) outputs.
For example, consider a program which outputs addresses for people to generate mailers. Most people have one address. Some have two or more. Some people, unfortunately, have none. Flatmap is a generalized algorithm to take a list of these people and return all of the addresses, regardless of how many come from each person.
The zero output case is particularly useful for monads, which often (always?) return exactly zero or one results (think Maybe- returns zero results if the computation fails, or one if it succeeds). In that case you want to perform an operation on "all of the results", which it just so happens may be one or many.
The "flatMap", or "bind", method, provides an invaluable way to chain together methods that provide their output wrapped in a Monadic construct (like List, Option, or Future). For example, suppose you have two methods that produce a Future of a result (eg. they make long-running calls to databases or web service calls or the like, and should be used asynchronously):
def fn1(input1: A): Future[B] // (for some types A and B)
def fn2(input2: B): Future[C] // (for some types B and C)
How to combine these? With flatMap, we can do this as simply as:
def fn3(input3: A): Future[C] = fn1(a).flatMap(b => fn2(b))
In this sense, we have "composed" a function fn3 out of fn1 and fn2 using flatMap, which has the same general structure (and so can be composed in turn with further similar functions).
The map method would give us a not-so-convenient - and not readily chainable - Future[Future[C]]. Certainly we can then use flatten to reduce this, but the flatMap method does it in one call, and can be chained as far as we wish.
This is so useful a way of working, in fact, that Scala provides the for-comprehension as essentially a short-cut for this (Haskell, too, provides a short-hand way of writing a chain of bind operations - I'm not a Haskell expert, though, and don't recall the details) - hence the talk you will have come across about for-comprehensions being "de-sugared" into a chain of flatMap calls (along with possible filter calls and a final map call for the yield).
Well, one could argue, you don't need .flatten either. Why not just do something like
#tailrec
def flatten[T](in: Seq[Seq[T], out: Seq[T] = Nil): Seq[T] = in match {
case Nil => out
case head ::tail => flatten(tail, out ++ head)
}
Same can be said about map:
#tailrec
def map[A,B](in: Seq[A], out: Seq[B] = Nil)(f: A => B): Seq[B] = in match {
case Nil => out
case head :: tail => map(tail, out :+ f(head))(f)
}
So, why are .flatten and .map provided by the library? Same reason .flatMap is: convenience.
There is also .collect, which is really just
list.filter(f.isDefinedAt _).map(f)
.reduce is actually nothing more then list.foldLeft(list.head)(f),
.headOption is
list match {
case Nil => None
case head :: _ => Some(head)
}
Etc ...

Monad transformer in Scala for comprehension to handle Option and collect error messages

I've been looking at a lot of Scala monad transformer examples and haven't been able to figure out how to do what I think is probably something straightforward. I want to write a for comprehension that looks up something in a database (MongoDB), which returns an Option, then if that Option is a Some, looks at its contents and gets another Option, and so on. At each step, if I get a None, I want to abort the whole thing and produce an error message like "X not found". The for comprehension should yield an Either (or something similar), in which a Left contains the error message and a Right contains the successful result of the whole operation (perhaps just a string, or perhaps an object constructed using several of the values obtained along the way).
So far I've just been using the Option monad by itself, as in this trivial example:
val docContentOpt = for {
doc <- mongoCollection.findOne(MongoDBObject("_id" -> id))
content <- doc.getAs[String]("content")
} yield content
However, I'm stuck trying to integrate something like Either into this. What I'm looking for is a working code snippet, not just a suggestion to try \/ in Scalaz. I've tried to make sense of Scalaz, but it has very little documentation, and what little there is seems to be written for people who know all about lambda calculus, which I don't.
I'd "try" something like this:
def tryOption[T](option: Option[T], message:String ="" ):Try[T] = option match {
case Some(v) => Success(v)
case None => Failure(new Exception(message))
}
val docContentOpt = for {
doc <- tryOption(mongoCollection.findOne(MongoDBObject("_id" -> id)),s"$id not found")
content <- tryOption(doc.getAs[String]("content"), "content not found")
} yield content
Basically an Option to Try conversion that captures the error in an exception. Try is an specialized right-biased Either that is monadic (in contrast to Either, which is not)
Try may be what you're looking for, but it's also possible to do this using the "right projection" of the standard library's Either:
val docContentOpt: Either[String, String] = for {
doc <- mongoCollection.findOne(MongoDBObject("_id" -> id)).toRight(
s"$id not found"
).right
content <- doc.getAs[String]("content").toRight("Can't get as content").right
} yield content
This may make more sense if your error type doesn't extend Throwable, for example, or if you're stuck on 2.9.2 or earlier (or if you just prefer the generality of Either, etc.).
(As a side note, it'd be nice if the standard library provided toSuccess and toFailure methods on Option that would make converting Option into Try as convenient as converting Option into Either is here—maybe someday.)
(And as another side note, Scalaz doesn't actually buy you much here—it would allow you to write .toRightDisjunction("error") instead of .toRight("error").right, but that's about it. As Gabriel Claramunt points out in a comment, this isn't a case for monad transformers.)

Scala, how to use Some(value) from an Option implicitly?

I have a piece of code that extracts a string from a request body, but it may not be there, so it is an Option[String]. If there is a value, then I wish to use it implicitly.
To do this conversion, I write implicit val code = googleCode.
Is there a way to make googleCode an implicit String so that I can use it directly rather than creating an implicit val with the value of googleCode?
request.getQueryString("code") match {
case None =>
Logger.error("unable to retrieve authentication code from google request")
Redirect(routes.Application.index())
case Some(googleCode) => Async {
implicit val code: String = googleCode // <== CONVERTING TO AN IMPLICIT
Logger.debug("retrieved authentication code, proceeding to get token")
...
Ok("congratulations, ${user.name}, you are logged in!")
Note, the code snippet is from a Playframework Controller, but this is more a question of the Scala language in general
It's often advisable to avoid using pattern matching with Options anyway. Here's how you can write it:
request.getQueryString("code") map { implicit googleCode =>
// googleCode is an implicit String! do something with it
} getOrElse {
// handle the None case
}
Hmm. Instead of looking for a solution for converting a code using Option into some kind of Java, I would suggest to take these three easy steps.
Step 1. Do whatever is the shortest cut for you, like option.get(), anything, so that your code (kind of) works.
Step 2. Learn functional programming. Specifically, learn to use Option in a idiomatic, specifically FP-style way.
Step 3. Profit. You will benefit a lot from learning.