scala – PartialFunction orElse在其类型边界上是否比它应该更
让我们定义一个PartialFunction [String,String]和一个PartialFunction [Any,String]
现在,给出orElse的定义 def orElse[A1 <: A,B1 >: B](that: PartialFunction[A1,B1]): PartialFunction[A1,B1] 我希望不能把这两者组合起来,因为 A→字符串 因此,绑定的A1<:A(即Any< ;: 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< ;: Animal. 以同样的方式,如果你有 def foo(l: List[Animal]) 你可以将List [Dog]传递给它,因为List与它的类型参数是协变的,因为Dog< ;: 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,这样 为此,它将寻找: > Any和String的最大公共子类型,因为A和A1处于逆变位置 结果 > A1→字符串 使用PartialFunction [Int,Int]组成PartialFunction [String,String]的情况是前一个示例的奇怪情况,其中: > String和Int的最大公共子类型是带Int的String,即两种类型的部分,它们都是两者的子类型(在这种情况下几乎就是说Nothing:既是String又是Int似乎不是很可能) 因此 val a: PartialFunction[String,String] = ... val b: PartialFunction[Int,Int] = ... a orElse b // PartialFunction[String with Int,Any] // as expected,although not very useful... (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |