加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – PartialFunction orElse在其类型边界上是否比它应该更

发布时间:2020-12-16 18:41:23 所属栏目:安全 来源:网络整理
导读:让我们定义一个PartialFunction [String,String]和一个PartialFunction [Any,String] 现在,给出orElse的定义 def orElse[A1 : A,B1 : B](that: PartialFunction[A1,B1]): PartialFunction[A1,B1] 我希望不能把这两者组合起来,因为 A→字符串 A1→任意 因此,
让我们定义一个PartialFunction [String,String]和一个PartialFunction [Any,String]

现在,给出orElse的定义

def orElse[A1 <: A,B1 >: B](that: PartialFunction[A1,B1]): PartialFunction[A1,B1]

我希望不能把这两者组合起来,因为

A→字符串
A1→任意

因此,绑定的A1<:A(即Any&lt ;: String)不成立. 出乎意料的是,我可以编写它们并获得在整个String域上定义的PartialFunction [String,String].这是一个例子:

val a: PartialFunction[String,String] = { case "someString" => "some other string" }
// a: PartialFunction[String,String] = <function1>

val b: PartialFunction[Any,String] = { case _ => "default" }
// b: PartialFunction[Any,String] = <function1>

val c = a orElse b
// c: PartialFunction[String,String] = <function1>

c("someString")
// res4: String = some other string

c("foo")
// res5: String = default

c(42)
// error: type mismatch;
//   found   : Int(42)
//   required: String

而且,如果我明确提供orElse类型参数

a orElse[Any,String] b
// error: type arguments [Any,String] do not conform to method orElse's type parameter bounds [A1 <: String,B1 >: String]

编译器最终显示出某种意义.

是否有任何类型的系统巫术我错过了导致b成为orElse的有效参数?换句话说,为什么A1被推断为String?

如果编译器从b推断出A1然后它必须是Any,那么导致String的推理链在哪里开始呢?

更新

在使用REPL后,我注意到当类型不匹配时,orElse返回与A1的交集类型A.例:

val a: PartialFunction[String,String] = <function1>

val b: PartialFunction[Int,Int] = { case 42 => 32 }
// b: PartialFunction[Int,Int] = <function1>

a orElse b
// res0: PartialFunction[String with Int,Any] = <function1>

从(String with Int)<:<字符串这是有效的,即使结果函数实际上不可用.我也怀疑String with Any被统一到Any中,鉴于此

import reflect.runtime.universe._
// import reflect.runtime.universe._   

typeOf[String] <:< typeOf[String with Any]
// res1: Boolean = true

typeOf[String with Any] <:< typeOf[String]
// res2: Boolean = true

这就是为什么将String和Any结果混合到String中的原因.

话虽如此,引擎盖下发生了什么?统一不匹配类型的逻辑是什么?

更新2

我已将问题简化为更一般的形式:

class Foo[-A] {
  def foo[B <: A](f: Foo[B]): Foo[B] = f
}

val a = new Foo[Any]
val b = new Foo[String]

a.foo(b) // Foo[String] Ok,String <:< Any
b.foo(a) // Foo[String] Shouldn't compile! Any <:!< String
b.foo[Any](a) // error: type arguments [Any] do not conform to method foo's type parameter bounds [A <: String]

解决方法

你是颠倒了.

您总是可以传递给需要类型A的参数的方法,任何类型为B<:A的参数,即A的任何子类型.如果你有

def foo(a: Animal)

你可以将狗传给foo,因为Dog&lt ;: Animal.

以同样的方式,如果你有

def foo(l: List[Animal])

你可以将List [Dog]传递给它,因为List与它的类型参数是协变的,因为Dog&lt ;: Animal,然后List [Dog]<:List [Animal] 现在,如果你有

def foo(pf: PartialFunction[String,String])

你可以传递一个PartialFunction [Any,String],因为PartialFunction与第一个类型参数是逆变的,而与第二个参数是协变的.由于Any> gt;:String,然后是PartialFuncion [Any,String]<:PartialFunction [String,String]. 现在,对于类型边界,编译器将尝试推断A1和B1,这样
> A1是A的子类型
> B2是B的亚型

为此,它将寻找:

> Any和String的最大公共子类型,因为A和A1处于逆变位置
>最小的String和String的超类型,因为B和B1是协变位置

结果

> A1→字符串
> B1→字符串

使用PartialFunction [Int,Int]组成PartialFunction [String,String]的情况是前一个示例的奇怪情况,其中:

> String和Int的最大公共子类型是带Int的String,即两种类型的部分,它们都是两者的子类型(在这种情况下几乎就是说Nothing:既是String又是Int似乎不是很可能)
> String和Int的最不常见的超类型是Any

因此

val a: PartialFunction[String,String] = ...
val b: PartialFunction[Int,Int] = ...
a orElse b // PartialFunction[String with Int,Any] // as expected,although not very useful...

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读