Reputation: 441
In Scala, I have an Array[Option[(String,String,Try[String])]]
and would like to find all the Failure error codes.
If the inner monad is an Option[String]
instead, I can access the Some(x)
contents with a clean little for comprehension, like so:
for {
Some(row) <- row
(a,b,c) = row
x <- c
} yield x
But if the inner monad is a Failure, then I'm struggling to see how to pattern match it, since I can't put Failure(x) <- c
in the for statement. This feels like a really simple thing I'm missing, but any guidance would be very valuable.
Many thanks!
EDIT - Mis-specified the array. It's actually an array of option-tuple3s, not just tuple3s.
Upvotes: 2
Views: 679
Reputation: 3692
Will a.map(_._3).filter(_.isFailure)
do?
EDIT: after having seen the edit and your comment, I think you can also do
val tries = for {
x <- a
z <- x
} yield z._3
tries.filter(_.isFailure)
Upvotes: 4
Reputation: 51271
This returns an Array[Throwable]
.
for {
(_,_,Failure(e)) <- rows
} yield e
Or, perhaps, an un-sugared version.
rows.collect{case (_,_,Failure(e)) => e}
Upvotes: 2
Reputation: 2480
In order to combine different types of "monads" you will need what's called a monad transformer. To put it simply, Scala doesn't let you mixin different monad types within the same for comprehension - this makes sense since a for comprehension just syntactic sugar for combinations of map / flatMap / filter.
Assuming the first one is always an Option
then you could transform the Try
into an Option
and get the desired result:
for {
Some((a, b, c)) <- row
x <- c.toOption
} yield x
If you don't really care about what's inside that Try
that's fine, but if you do then be careful that you'll lose that information when doing Some(x)
. If the pattern match fails, then you will get a None
.
I hope that helps you.
Upvotes: 3