Scala:提取器对象的问题,类型推断

时间:2018-03-28 21:41:28

标签: scala pattern-matching

json4 has以下类型:

sealed abstract class JValue
case class JString(s: String) extends JValue
//etc

我有以下json值:

    val json: JValue = JString("hi")

我将其用于理解中:

val token = for {
  JString(s) <- json
} yield s

以下是问题:

  1. 实际上,令牌将被评估为List("hi"),即List[String]类型的实例。我的理解是它应该是Option[String]。为什么Option - &gt; List

  2. IntelliJ的类型 - “推理”帮助器,建议为for-comprehension的结果设置类型JValue。然而,当你这样时,你会收到编译错误。这里有什么问题?为什么会发生混乱?

1 个答案:

答案 0 :(得分:1)

  1. 为什么List[String]
  2. 好吧,你可以看到here,这就是json4s作者所选择的。他们本可以使用Vector[String]Array[String],但决定List[String]。我认为他们有充分的理由。

    withFilter()与它有什么关系?

    正如我们在Scala类的第一天所学到的,for不是一个控制流语言构造,但实际上是用于美化嵌套map / flatMap构造的语法糖

    for {
      b <- a               // flatMap()
      if b.isSomeCondition // withFilter()
      c <- b               // map()
    } yield c
    

    事实证明,withFilter()构造中的模式匹配时也使用for。所以这......

    for {
      JString(s) <- json
    } yield s
    

    ...被翻译成这个(大致)。

    json.withFilter{
      case JString((s @ _)) => true
      case _ => false
    }.map{
      case JString(s @ _) => s
    }
    

    json4s的作者认为withFilter()应该返回List,因此这是for理解的结果。

    1. IntelliJ的困惑。
    2. IntelliJ的语法检查和建议引擎非常好,但它并不完美。 Scala代码可能变得相当复杂,IntelliJ混淆并不罕见。相信编译器。如果它在没有警告的情况下编译,那么只需忽略错误类型的建议。