Question

Is there an equivalent to the OO notion of subtyping for the ADT pattern as used in Scala? In particular I would like to add methods to more specialized types. For example, given a generic List ADT:

sealed trait List[+A]
case class Cons[+A](h: A, t: List[A]) extends List[A]
case object Nil[Nothing]

I'd like to define new methods for lists of particular types:

sealed trait List[+A]
sealed trait DuckList extends List[Duck] {
    def feed(l: DuckList) = ...
}

but then I'd also have to define special data constructors (DuckCons, DuckNil) for these new types, and since case classes don't support (case-to-case) inheritance, there is no way to relate a DuckCons to the generic Cons such that it would work in pattern matching, so the generic methods defined for List wouldn't work for DuckList.

Était-ce utile?

La solution

Use the type class pattern.

For one example, consider how Ordering is implemented. It adds a method -- compare -- to a set of closed classes, but it does so not by adding the method directly but, instead, providing an instance that has such a method for that particular class. Ordering[Int], to continue with the example, is implemented like this:

trait IntOrdering extends Ordering[Int] {
  def compare(x: Int, y: Int) =
    if (x < y) -1
    else if (x == y) 0
    else 1
}
implicit object Int extends IntOrdering

That is, the object Ordering.Int (for this is inside the object Ordering) implements a method compare that takes two Int as a parameter. This object is provided implicitly, so that the user does not need to pass it explicitly. List's sorted method takes advantage of this:

def sorted[B >: A](implicit ord: math.Ordering[B]): List[A]

Then it can call ord.compare on instances of the list to order them. I encourage you to look at Ordering to understand what it is doing.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top