使用orElse链接选项更改了元素类型

时间:2012-08-28 09:47:01

标签: scala

我发现在使用orElse链接Option之后,元素类型发生了变化,这使我无法按预期使用它。

例如:一个类型为NodeSeq的xml。

scala> xml1.headOption map { head => None } orElse xml2.lastOption map {last => Some(last)}
res11: Option[Some[ScalaObject with Equals]] = Some(Some(None))

orElse之前,head的类型为Node,这是正确的,但last也应该是Node类型,但编译器认为它的类型为ScalaObject with Equals,我无法将last传递给函数,并将Node作为参数。

我可以使用last.asInstanceOf[Node]来投射它,有没有办法避免这种投射,仍然可以last类型Node

3 个答案:

答案 0 :(得分:3)

请尝试这样做(注意添加的括号):

(xml.headOption map { head => None }) orElse (xml.lastOption map {last => Some(last)})

问题是在map之后而不是在orElse之前应用orElse。换句话说,表达式解析如下:

((xml.headOption map { head => None }) orElse xml.lastOption) map {last => Some(last)}

由于orElse左侧的表达式具有类型Option[Option[Node]],但右侧表达式的类型为Option[Node],因此最低常见超类型为Option[ScalaObject with Equals] }。

Scala灵活的语法有时会使编码变得非常好,但有时会导致像这样的疯狂事情。对于像这样的复杂表达式,最好添加括号以使您的意思更明确。

答案 1 :(得分:1)

总的来说,我认为你需要重新审视自己到底在做什么,因为它没有多大意义。 xml.headOption map { head => None }始终会解析为Some(None)(在您的情况下),这很少是您想要的。我最好的猜测是你想要的东西:

xml.headOption.orElse(xml.lastOption)

虽然值得注意的是,如果headOption为None,那么lastOption也是如此。

编辑:正如道文指出的那样,在这个例子中很有可能推断出Option[Node]的正确上限,并且模糊它的问题是被调用的错误orElse。但是,我仍然认为这里真正的问题是你所做的事情没有多大意义,应该重新考虑。

答案 2 :(得分:0)

map {head => None}可能不是你想要的。这是一个错字?

之后,您有一个Option[None.type],一个不太有趣的类型,它只有两个可能的值,NoneSome(None)。 由于您的xml不为空,它恰好是Some(None)。

xml.LastOption的类型为Option[Node]

因此,当你在orElse之间进行操作时,它会查找None.typeNode的最精确的常见超类型(最小上限)。并且没有任何兴趣,它恰好是ScalaObject with Equals,它也可能是AnyRef

你的最终map {last => Some(last)}也很奇怪。你打算做什么?