我试图压扁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应该适用于这种情况。
答案 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]
。编译器必须在编译时解析此参数,否则由于缺少参数,方法调用无效。因此,在编译时,编译器会发现A
为Any
(来自get(key)
),B
为Option[C]
(来自flatten
'签名)。由于无法证明关系Any <: Option[C]
,因此会出现错误。
想象一下,如果此代码 有效,会发生什么。然后,如果发生任何事情使您的地图返回Some(5)
而不是Some(Some(blah))
,您仍然会尝试拨打Some(5).flatten
,然后尝试将5转换为Option
然后......哎呀。即使你的程序逻辑确保你的地图给你一个嵌套的Option
,编译器显然不是魔术,也不能确定。
您可以使用部分函数或match
来完成这项工作,因为在运行时检查案例而不是编译时间,并且任何与案例不匹配的内容都会抛出MatchError
而不是被编译器抓住了。
TL; DR 广义类型约束在编译时解析,这在此处是不可能的,因为返回类型为Option[Any]
。