【问题标题】:Why doesn't scala.util.Try implement GenTraversableOnce?为什么 scala.util.Try 不实现 GenTraversableOnce?
【发布时间】:2013-11-09 12:35:39
【问题描述】:

感谢 Martin Odersky 在 Coursera 上提供的最新产品,我已经开始使用 scala.util.Try。然而,我惊讶地发现它不一定能很好地与集合 monad 配合使用,因为它没有实现 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 实际上不是一个单子吗?

【问题讨论】:

  • 对于它的价值,我从来没有特别喜欢Option 的成语(尽管我使用它并且它从未咬过我)。有一个显式的 catMaybes 似乎比通过隐式转换混合 monad 更好。
  • 更重要的是:Option 可以很自然地被视为最大长度为 1 的集合。以同样的方式查看Try 意味着忽略其部分语义。有时这样做是有意义的(这就是toOption 存在的原因),但您不希望它意外发生。
  • @TravisBrown 谈到函数式编程,我仍然是新手,到目前为止,Scala 是我唯一的语言。话虽如此,我没有认识到 Scala Option 和 Haskell Maybe 之间的任何区别。有没有我遗漏的细微差别?
  • @TravisBrown 我在您的第二条评论中看到了您的观点。也许原因是压制Failure 的情况应该是明确的。
  • @TravisBrown 将您的 cmets 关于集合和 Try 之间的语义差异作为答案,我将结束这个问题。

标签: scala monads implicit-conversion


【解决方案1】:

这是一个 Monad,但在我看来,它真的不是你尝试使用它的方式的集合。 FlatMap 不适用于在不同 monad 之间进行转换(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)

【讨论】:

    猜你喜欢
    • 2019-02-14
    • 2016-01-27
    • 2017-04-11
    • 1970-01-01
    • 2020-05-18
    • 2017-02-09
    • 1970-01-01
    • 2010-09-25
    • 2011-06-23
    相关资源
    最近更新 更多