Scala 推理 : fail on 1 evaluation, 成功并具有中间值

标签 scala type-inference

我是 Scala 的初学者,不明白这里发生了什么:

给定:

val reverse:Option[MyObject] = ...

并且myObject.isNaire返回 bool 值。

如果我这样做:

val v:Option[Boolean] =  reverse.map(_.isNaire)
val b:Boolean = v.getOrElse(false)

它有效。

现在,如果我这样做:

val b:Boolean = reverse.map(_.isNaire).getOrElse(false)

它无法编译,类型不匹配:找到任何,必需的 bool 值


编辑:谢谢Beryllium,通过制作SSCCE,我找到了解释的开始。在第一个示例中,myObject 是一个 java 类,因此 isNaire 是一个 java.lang.Boolean。我认为隐式转换应该使这一过程变得透明,因此仍然欢迎解释。

class Test(val naire:java.lang.Boolean)

class Other {
  val testValue = Some(new Test(true))
  def mysteriousCompilationError:Boolean = testValue.map(_.naire).getOrElse(false)
}

注意:ScalaCompiler 是 2.10.2

最佳答案

scala.Predef 中,有一个从 java.lang.Booleanscala.Boolean 的隐式转换:

  implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.booleanValue

因此,在第一种情况下,编译器会看到 java.lang.Boolean 并查找作用域中的隐式方法,将其转换为 scala.Boolean,可以方便地在 scala.Predef 中找到它。

在第二种情况下,testValue.map(_.naire).getOrElse(false),编译器按以下顺序执行操作:

  1. 选项[测试] => 选项[java.lang.Boolean]
  2. getOrElse[B >: A](默认值:=> B): B 其中 Ajava.lang.BooleanBAny,因为 scala.Boolean 不是 >: java.lang.Boolean
  3. val b:Boolean,编译器找不到从 Anyscala.Boolean 的隐式转换

解决这个问题的唯一方法是在映射操作期间告诉编译器使用从 scala.Predefjava.lang.Boolean 的隐式转换> 到 scala.Boolean:

def works:Boolean = testValue.map[Boolean](_.naire).getOrElse(false)

这是一个常见问题,并且经常出现,因为 map 后跟 getOrElse 非常方便。要在没有额外类型的情况下正确修复此问题,请在选项上使用 fold (变形):

def worksToo:Boolean = testValue.fold(false)(_.naire)

通过使用fold,您可以获得一些额外的类型安全性,因为没有转换为常见类型。例如,您不能这样做:

def failsTypeCheck = testValue.fold("test")(_.naire)

虽然编译器对此没有问题:

def passesTypeCheck = testValue.map(_.naire).getOrElse("test")

关于Scala 推理 : fail on 1 evaluation, 成功并具有中间值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18045985/

相关文章:

function - 在Scala中自动将类方法转换为采用显式类参数的函数的方法?

scala - "tee"Scala 流/迭代器

scala - 查找 Array[Int] 的第一个空值

rust - 动态闭包 Vec 的错误类型推断

C++模板参数类型推断

scala - 给定非交换关联操作,foldRight 是否等同于 foldLeft?

java - Scala Spring 检查空片段

ocaml - 任意深度的步行 OCaml 元组

rust - Rust 中的左值上下文到底是什么?

haskell - 使用 Rank2Types 代替 RankNTypes 有什么优势吗?