Conditional methods of Scala generic classes with restrictions for type parameters

穿精又带淫゛_ 提交于 2020-02-13 08:42:51

问题


I believe that a generic class may make one of its methods available only assuming that its type parameters conform to some additional restrictions, something like (syntax improvised on the spot):

trait Col[T] extends Traversable[T] {
    def sum[T<:Int] :T = (0/:this)(_+_)
}

I guess I could use implicit parameters as evidence... Is there a language feature for this?


回答1:


In this case you can only use an implicit parameter, as the type gets determined before the method call.

trait Col[T] extends Traversable[T] {
  def sum(implicit num: Numeric[T]) :T = ???
}

If the method you are calling would be parameterized, you could use context bounds, which are just syntactic sugar for the implicit parameter bound to the type parameter:

def foo[A](implicit ev: Something[A]) = ???

is equivalent to

def foo[A : Something] = ???



回答2:


You can also use a type bound on the type parameter, which is enforced by an implicit argument:

trait Col[T] extends Traversable[T] {
    def sum(implicit ev: T <:< Int) :T = (0/:this)(_+_)
}

<:< is actually a class, expressed in infix notation, defined in Predef.scala and explained in many places, including here

<:< means 'must be a subtype of'

You can also use =:= 'must be equal to' and X <%< Y 'must be viewable as' (ie. there is an implicit conversion to X from Y)

For a more detailed explanation of type constraints, see this SO question.




回答3:


there is another option involving implicit classes conversions

trait Col[T] extends Traversable[T] 

implicit class ColInt[T <: Int](val v : Col[T]) extends AnyVal {
    def sum : T = (0 /: v)(_ + _)
}

in this context you don't need the empty trait Col anymore, so you could further comprimize it to this:

implicit class ColInt[T <: Int](val v : Traversable[T]) extends AnyVal {
    def sum : T = (0 /: v)(_ + _)
}

The advantage of this method is, that it tells the compiler, that type T is really a subtype of Int, so List[T] <: List[Int] is still valid in this context, and no explicit conversion needs to be added. The implicit parameter adds implicit conversions that wouldn't work on List[T], because it only introduces an implicit conversion from T to Int, not from List[T] to List[Int]



来源:https://stackoverflow.com/questions/17794873/conditional-methods-of-scala-generic-classes-with-restrictions-for-type-paramete

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!