尝试选项时出错(选项(某些))。在Scala中展平

时间:2016-07-13 15:55:16

标签: scala

我试图压扁Option(Option(Some)),但是当我尝试编译代码时,我收到错误。

代码如下:

val foo = request.options.get(myKey).flatten
if(foo.get == bar) {...}

其中request.option.get(Key)返回Option[Any]。在这种情况下,与myKey相关联的值为Option,因此request.options.get(myKey) 应该返回Option(Option(Some)),我在调试此代码时已经看到了。{/ p>

但是,我收到以下错误:

Error: Cannot prove that Any <:< Option[B].

Error: not enough arguments for method flatten: (implicit ev: <: <[Any,Option[B]])Option[B]
Unspecified value parameter ev.

据我所知,flatten应该适用于这种情况。

2 个答案:

答案 0 :(得分:1)

request.options.get(key)返回Option[T]这一事实并不意味着request.options.get(Some(key))返回Option[Option[T]]。我认为您要做的是在将key传递给Some之前将其get传递出来:

val theValueIWant = for {
  k <- myKey                   // get k out of the Some
  op <- request.options.get(k) // get the option (Some(value) or None)
  value <- op                  // get the value out of the option
} yield value

答案 1 :(得分:0)

只是因为您看到get(key)运行时返回嵌套Option 并未改变编译时签名的事实该方法只能确保它返回Option[Any]。这就是编译器所抱怨的。它可以证明您有Option[Any],但无法证明您在编译时Option[Option[_]]

A <:< B的工作方式是它只是<:<[A, B]类型的语法糖。此类型表示编译器知道A <: B的证据。它的存在见证了这一事实。如果编译器无法以某种方式证明该关系,则A <:< B没有值。因此,flatten是一个普通方法,其隐式参数类型为<:<[A,B]。编译器必须在编译时解析此参数,否则由于缺少参数,方法调用无效。因此,在编译时,编译器会发现AAny(来自get(key)),BOption[C](来自flatten'签名)。由于无法证明关系Any <: Option[C],因此会出现错误。

想象一下,如果此代码 有效,会发生什么。然后,如果发生任何事情使您的地图返回Some(5)而不是Some(Some(blah)),您仍然会尝试拨打Some(5).flatten,然后尝试将5转换为Option然后......哎呀。即使你的程序逻辑确保你的地图给你一个嵌套的Option,编译器显然不是魔术,也不能确定。

您可以使用部分函数或match来完成这项工作,因为在运行时检查案例而不是编译时间,并且任何与案例不匹配的内容都会抛出MatchError而不是被编译器抓住了。

TL; DR 广义类型约束在编译时解析,这在此处是不可能的,因为返回类型为Option[Any]