Scala:约束成员函数的类类型参数

Mic*_*ier 1 types scala

给定一个A具有类型参数的类,T我如何进一步约束T特定函数?在下面的示例中,我想强制执行foo只能在TInt(或子类型,如果您愿意)时调用。即new A[Int]().foo()应该编译,但new A[Double]().foo()不应该编译。

我可以通过隐式转换实现我想要的,T => Intfoo. 然而,这会导致不必要的方法调用 - 隐式找到的证据是身份函数。还有,不好看。。。

class A[T] {
  val someValue: T = ???

  def foo()(implicit ev: T => Int): Int = ev(someValue)

  // some ideas that don't quite work
  // def bar[T2 <: Int :EqualTo[T]](t2: T2): T = t2.asInstanceOf[T]
  // def bam[T2 <: T with Int](): Int = someValue.asInstanceOf[Int]

  def thisOneDefinesItsOwnConstraintType[Z <: Int](z: Z): Z = z
  def thisOneDoesNotNeedToConstrainT(t: T): T = someValue
}
Run Code Online (Sandbox Code Playgroud)

如果不需要施法,该解决方案将获得奖励积分:)

注意:我知道我可以在类或方法级别定义类型约束(请参阅 参考资料thisOneDefinesItsOwnConstraintType),但这对我没有帮助,因为我还有一些不需要约束类型的方法(请参阅 参考资料thisOneDoesNotNeedToConstrainT)。

Mic*_*jac 5

我没有看到没有隐式的方法,因为虽然您可以B <: C对类方法施加一些约束,但您的要求B <: T很难概括,因为我们不知道C与 arbitary有什么关系T。幸运的是,Scala 已经为此提供了一个构造,即<:<类型类。<:<[B, T]生成的实例Predef将提供证据表明B <: C.

但不要只相信我的话,这是scaladoc必须说的:

要限制方法参数列表范围内的任何抽象类型 T(不仅仅是方法自己的类型参数),只需添加类型 T <:< U 的隐式参数,其中 U 是所需的上限;或对于下限,使用:L <:< T,其中 L 是所需的下限。

例如:

class E
class F extends E
class G extends F

class A[T] {
  def constrained[B <: F](b: B)(implicit ev: B <:< T): B = b
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们引入了方法的Ffor 类型参数的上限。但是,如果你想保证(不添加其他类型的参数),你可以添加隐。BcontrainedB <: TB <:< T

scala> val a = new A[E]
a: A[E] = A@5a63f509

scala> a.constrained(new E)
<console>:15: error: inferred type arguments [E] do not conform to method constrained's type parameter bounds [B <: F]
       a.constrained(new E)
         ^
<console>:15: error: type mismatch;
 found   : E
 required: B
       a.constrained(new E)
                     ^

scala> a.constrained(new F)
res5: F = F@4a668b6e

scala> a.constrained(new G)
res6: G = G@4de4b452
Run Code Online (Sandbox Code Playgroud)