Thanks to the latest offering from Martin Odersky on Coursera, I have begun playing with scala.util.Try
. However, I was surprised to find that it doesn't necessarily play well with the collection monads because it doesn't implement scala.collection.GetTraversableOnce
.
This could come in handy. For instance, you could convert a list of strings to integers while throwing out the bad ones like this:
def ints(strs:List[String]):List[Int] = strs.flatMap(s => Try(s.toInt))
The workaround is simple. Just convert the Try
to an Option
and let its implicit conversion work for us:
def ints(strs:List[String]):List[Int] = strs.flatMap(s => Try(s.toInt).toOption)
Seems to me that Try
would either implement GenTraversableOnce
or have its own implicit conversion. Can anyone explain why it doesn't? Is it simply the fact Try
isn't actually a monad?
It's a Monad, but in my opinion, it's really not a collection in the way you're trying to use it. FlatMap is not for translating between different monads (M[A]=>M[B]
, yes, but not M[A]=>N[B]
or even M[A]=>N[A]
). It feels more like you want something like:
import scala.util.{Try, Success}
def ints2(strs: List[String]): List[Int] =
strs.map { s => Try(s.toInt) }.collect { case Success(n) => n }
or
import scala.util.{Try, Success, Failure}
def ints3(strs: List[String]): List[Int] = strs.flatMap { s =>
Try(s.toInt) match {
case Success(n) => List(n)
case Failure(ex) => List.empty
}
}
=>
scala> ints2(List("1","2","a","3"))
res8: List[Int] = List(1, 2, 3)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With