Почему не scala.util.Try реализовать GenTraversableOnce?
Благодаря последнему предложению Мартина Одерски на Coursera, я начал играть с scala.util.Try
. Однако я с удивлением обнаружил, что он не обязательно хорошо сочетается с коллекционными монадами, потому что он не реализует scala.collection.GetTraversableOnce
.
Это может пригодиться. Например, вы можете преобразовать список строк в целые числа, выбрасывая плохие, например:
def ints(strs:List[String]):List[Int] = strs.flatMap(s => Try(s.toInt))
Обходной путь прост. Просто преобразуйте Try
в Option
и пусть его неявное преобразование работает для нас:
def ints(strs:List[String]):List[Int] = strs.flatMap(s => Try(s.toInt).toOption)
Мне кажется, что Try
будет либо реализовывать GenTraversableOnce
, либо иметь собственное неявное преобразование. Может ли кто-нибудь объяснить, почему это не так? Это просто факт, что Try
на самом деле не монада?
Ответы
Ответ 1
Это Монада, но, на мой взгляд, это действительно не коллекция, в которой вы пытаетесь ее использовать. FlatMap не предназначен для перевода между разными монадами (M[A]=>M[B]
, да, но не M[A]=>N[B]
или даже M[A]=>N[A]
). Это похоже на то, что вы хотите что-то вроде:
import scala.util.{Try, Success}
def ints2(strs: List[String]): List[Int] =
strs.map { s => Try(s.toInt) }.collect { case Success(n) => n }
или
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)