Scala PartialFunction orElse的类型界限是否比它应该的更宽松?
让我们定义一个Scala PartialFunction orElse的类型界限是否比它应该的更宽松?,scala,types,partialfunction,Scala,Types,Partialfunction,让我们定义一个PartialFunction[String,String]和一个PartialFunction[Any,String] 现在,给出orElse def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] 此外,如果我显式地提供orElse类型参数 a orElse[Any, String] b // error: type arguments [Any,S
PartialFunction[String,String]
和一个PartialFunction[Any,String]
现在,给出orElse
def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1]
此外,如果我显式地提供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]
因为
(带Int的字符串)我想说PartialFunction[Any,String]
是PartialFunction[String,String]
的一个子类型,因为如果我理解正确的话,是相反的。这可以解释你在更新前的问题中描述的行为,但是你把我和这个工会类型的东西搞混了
我甚至不知道带Int的字符串是什么意思 这当然是含糊不清的,只是我的拙见。欢迎提出建议和意见
从这个问题来看。()
这才有意义。如果您有一个来自Any=>String
的函数,那么它接受任何输入。因此它也接受字符串
输入。这就是为什么它也可以被视为String=>String
中的函数。对于任何T
,基本上都可以将其视为T=>String
因此,编译器最终同意A->String
和A1->String
a.orElse[String,String](b) //works
编辑:最后的想法
你不应该认为你已经输入了这个,但是:
scala> val a: PartialFunction[String, String] = { case "a" => "b" }
a: PartialFunction[String,String] = <function1>
scala> val b: PartialFunction[Any, String] = { case 1 => "one" }
b: PartialFunction[Any,String] = <function1>
scala> a orElse b
res0: PartialFunction[String,String] = <function1>
scala> a orElse[String,String] b
res1: PartialFunction[String,String] = <function1>
scala> a orElse[Any,String] b
<console>:10: error: type arguments [Any,String] do not conform to method orElse's type parameter bounds [A1 <: String,B1 >: String]
a orElse[Any,String] b
^
scala> import reflect.runtime._ ; import universe._
import reflect.runtime._
import universe._
scala> typeOf[PartialFunction[Any,String]] <:< typeOf[PartialFunction[String,String]]
res3: Boolean = true
scala>vala:PartialFunction[String,String]={case“a”=>“b”}
a:PartialFunction[字符串,字符串]=
scala>valb:PartialFunction[Any,String]={case1=>“one”}
b:部分函数[任何,字符串]=
scala>a orElse b
res0:PartialFunction[String,String]=
scala>a orElse[String,String]b
res1:PartialFunction[字符串,字符串]=
scala>a或[Any,String]b
:10:错误:类型参数[Any,String]不符合方法orElse的类型参数界限[A1:String]
a奥利斯[任何,字符串]b
^
scala>导入反射运行时;导入宇宙_
导入reflect.runtime_
导入宇宙_
scala>typeOf[PartialFunction[Any,String]]你把这个颠倒过来了
您总是可以传递给需要类型为a
的参数的方法,类型为B的任何参数都非常确定编译器只是推断出它能找到的最严格的返回类型。而不是反向推断其他类型?挑剔:“String with Int”不是联合类型,因为根据定义,作为一个联合类型需要“String”和“Int”独立完成“String with Int”接口,实际情况并非如此。“字符串”不是Thank@Utaal,它实际上是一个交叉点而不是一个联合体。修好了!这不是一个反差问题,类型界限非常具体:A1
(即Any
)必须是a
(即Any
)的子类型,这是错误的。差异在这里无关紧要。@GabrielePetronella A1我取消了我的反对票,因为我错了。然而,这个答案肯定需要一些详细说明。它是一个子类型,但不是一个子类。从总体上看,我也同意编译器的观点。但是我不明白这里遵循的推理规则是什么。b
的静态类型是PartialFunction[Any,String]
,这与PartialFunction[String,String]
不兼容,除非您决定将Any
向下转换为String
。编译器为什么要这样做?这个暗示来自哪里?是的,这个评论是错误的。这两个PartialFunction
都是子类型,但是Any
绝对不是String
的子类型。另外,Int
不是String
的子类型,但是orElse
适用于PF[Int,String]
和PF[String,String]
。谢谢,您上次的编辑似乎很合法。我仍然需要处理所有的信息(我甚至可能自己写下一个答案),但是你的输入非常有用。我个人也没有对这类东西做太多研究。我在这里部分依靠我的常识。我希望能有更多的知识和事实,而不是凭直觉得到一个更详细的答案。我得到了相反的观点,但Any
仍然不是String
的子类型,那么A1我怎么能对另一个答案发表评论呢。A1和A都是字符串。我的意思是,很明显,这是因为A1
的推断类型参数是String
,而不是Any
,但是为什么会发生这种推断呢?因为它有效吗?对不起,我要去学校接你了。您显示它不能与A1一样工作。我错过了将Any
静态推断为String
的精确规则。我相信这个解释是正确的,但我还是错过了这一点。“你把事情搞砸了。”你是用第二人称回答自己吗不管怎样,这似乎很好地概括了正在发生的事情。回答得很好!比我想象的要完整得多,虽然我觉得这里没有必要重新解释协方差和反方差,但感兴趣的人可以在其他地方找到它。尽管如此,仍然不能完全理解带有Int部分的字符串。也许我只是没有花足够的时间考虑这个问题,但是如果你真的想让你的答案更全面,你可能需要对此做一些详细的阐述。@Undercurrent想象一下:类a用C扩展B
。那么对于val a=new a
,以下都是正确的a.isInstanceOf[B]
,a.isInstanceOf[C]
和a.isInstanceOf[B with C]
。您始终使用和
进行继承。它将类型与和组合在一起。这是B和C同时出现。@Kigyo,准确地说,这就是我回答我的天真问题的方式,很有风格!关于解释逆变,我是向OP解释的,OP显然忘了它是什么:P
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
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]
import scala.reflect.runtime.universe._
implicit class MyInstanceOf[U: TypeTag](that: U) {
def myIsInstanceOf[T: TypeTag] =
typeOf[U] <:< typeOf[T]
}
val b: PartialFunction[Any, String] = { case _ => "default" }
b.myIsInstanceOf[PartialFunction[String, String]] //true
a.orElse[String,String](b) //works
scala> val a: PartialFunction[String, String] = { case "a" => "b" }
a: PartialFunction[String,String] = <function1>
scala> val b: PartialFunction[Any, String] = { case 1 => "one" }
b: PartialFunction[Any,String] = <function1>
scala> a orElse b
res0: PartialFunction[String,String] = <function1>
scala> a orElse[String,String] b
res1: PartialFunction[String,String] = <function1>
scala> a orElse[Any,String] b
<console>:10: error: type arguments [Any,String] do not conform to method orElse's type parameter bounds [A1 <: String,B1 >: String]
a orElse[Any,String] b
^
scala> import reflect.runtime._ ; import universe._
import reflect.runtime._
import universe._
scala> typeOf[PartialFunction[Any,String]] <:< typeOf[PartialFunction[String,String]]
res3: Boolean = true
def foo(a: Animal)
def foo(l: List[Animal])
def foo(pf: PartialFunction[String, String])
val a: PartialFunction[String, String] = ...
val b: PartialFunction[Int, Int] = ...
a orElse b // PartialFunction[String with Int, Any] // as expected, although not very useful...