Scala Puzzle:强制执行两个函数参数的类型相同,并且都是给定类的子类型

jhe*_*dus 7 types type-systems scala type-inference compilation

如何trickyMethod在编译时强制执行的参数是相同的,但同时也有共同的超类型Fruit

所以换句话说,tricky.trickyMethod(new Banana,new Apple)不应该编译.

我相信必须有一个简单的解决方案,但我只花了1个小时寻找答案,但仍然不知道:(

我用<:<尝试了隐含的证据,但我无法让它工作.

class Fruit
class Apple extends Fruit
class Banana extends Fruit

class TrickyClass[T<:Fruit]{
  def trickyMethod(p1:T,p2:T)= println("I am tricky to solve!")
}

object TypeInferenceQuestion extends App{
  val tricky=new TrickyClass[Fruit]()
  tricky.trickyMethod(new Apple,new Apple) //this should be OK
  tricky.trickyMethod(new Banana,new Banana) //this should be OK
  tricky.trickyMethod(new Banana,new Apple) //this should NOT compile

}
Run Code Online (Sandbox Code Playgroud)

编辑:

谢谢你的答案!

跟进(更一般)问题:

第二个例子是第一个例子的更一般情况.

class Fruit

class Apple extends Fruit
class Banana extends Fruit

class TrickyClass[T]{
  def trickyMethod[S<:T](p1:S,p2:S)= println("I am tricky to solve!")
}

object TypeInferenceQuestion extends App{
  val tricky=new TrickyClass[Fruit]()
  tricky.trickyMethod(new Apple,new Apple) //this should be OK
  tricky.trickyMethod(new Banana,new Banana) //this should be OK
  tricky.trickyMethod(new Banana,new Apple) //this should NOT compile

}
Run Code Online (Sandbox Code Playgroud)

Mar*_*rth 7

你可以这样做:

class Tricky[T] {
  def trickyMethod[S1<:T,S2<:T](s1:S1,s2:S2)(implicit ev: S1=:=S2) = println()
}


scala> val t = new Tricky[Seq[Int]]
t: Tricky[Seq[Int]] = Tricky@2e585191

scala> t.trickyMethod(List(1),List(1))
//OK

scala> t.trickyMethod(List(1),Seq(1))
<console>:10: error: Cannot prove that List[Int] =:= Seq[Int].
              t.trickyMethod(List(1),Seq(1))
Run Code Online (Sandbox Code Playgroud)