Brandon
Brandon

Reputation: 542

Scala generic type function restriction like F#

Is there any way of placing a restriction on the generic type A, in such a way that A must have a given method?. I know that in F# it can be done like this

type GenericState<'A when 'A:comparison>

Meaning that A must be a type that has a comparison function. I wonder if this can be easily done in Scala

Upvotes: 0

Views: 36

Answers (1)

flavian
flavian

Reputation: 28511

There are a couple.

Lower bound

trait Behaviour {
  def someMethod...
}

// GenericState has to inherit from Behaviour and therefore
// implement someMethod
type GenericState <: Behaviour

Context bounds

trait Behaviour[T] {
  def someMethod ..
}

// T has to inherit from GenericState and have
// an implicit Behaviour[T] in scope.
class Test[T <: GenericState : Behaviour] {
  // this is a good way to decouple things
  // You can get a reference to the materialized bound with implicitly
  // and call your method on that.
  implicitly[Behaviour[T]].someMethod(..)
}

Structural types

The most direct equivalency is not advised, as it doesn't have a performant implementation on the JVM.

// This creates a type definition in place and it's effectively similar
// to the first variant, except the type is structurally defined.
type GenericState <: {
  def someMethod ..
}

I would personally prefer the context bound here.

trait Comparable[T] {
  def compare(x: T, y: T): Int
}
object Comparable {
  implicit val intComparable = new Comparable[Int] {
    def compare(x: Int, y: Int): Int = ..
  }

 // and so on
}

Then whenever you need something comparable, you use context bounds.

class Something[T : Comparable](obj: T)

Which is just syntactic sugar for:

class Something[T](obj: T)(implicit ev: Comparable[T])

Upvotes: 2

Related Questions