Question

Hi I'm looking for a quick example of type class usage in Scala that will work in both 2.7.7 and 2.8 environments.

All of the examples that I've seen only work in 2.8, but I've been told that type classes are implementable in 2.7.7 as well.

The only other requirement is that the usage must be able to work in a script.

Any examples appreciated! Thanks

Was it helpful?

Solution 2

I went with a solution along these lines:

//---------- Classes without needed behavior
case class Point(x: Double, y: Double)
trait Shape {}
case class Circle(center: Point, radius: Double) extends Shape {}
case class Rectangle(lowerLeft: Point, upperRight: Point) extends Shape {}


val circle = Circle(Point(1.0, 2.0), 5.0)
val rectangle = Rectangle(Point(-2.0, -1.0), Point(4.0, 5.0))


//----------- Support for new behavior I want to add

// Create exception to handle non supported subclasses
case class NewMethodNotSupported(a: Any)
    extends RuntimeException(a.toString + ".newMethod() not supported")

class NewBehavior(shape: Shape) {
    def newMethod() = shape match {
        case c: Circle => doMethod(c)
        case r: Rectangle => doMethod(r)
        case _ => throw NewMethodNotSupported(shape)
    }
    private
    def doMethod(s: Shape) = println(s) // print to standard out.
}

object NewBehavior {
    // invoked by the compiler
    implicit def shapeToNewBehavior(s: Shape) = new NewBehavior(s)
}

// bring the implicit method in scope
import NewBehavior._
// --------- End of new behavior support        


// Test behavior support:
println("Test that new behavior is added:")
circle.newMethod()
rectangle.newMethod()

// Create a non supported shape class
case class Triangle(vertex1: Point,
        vertex2: Point, vertex3: Point) extends Shape {}

val triangle = Triangle(Point(-1.0,0.0), Point(1.0,0.0), Point(0.0,1.0))

// Catch exception thrown by trying to call method from unsupported shape
try{    
    println("\nTest method call from unsupported shape:")
    triangle.newMethod()
} catch {
    case dns: NewMethodNotSupported => println(dns); System.exit(-1)
    case unknown => println("Uknown exception " + unknown); System.exit(-1)
}

OTHER TIPS

I suppose you could do something like this:

def max[A](list: List[A])(implicit ord: Ordering[A]): A = {
  list.tail.foldLeft(list.head) ((a, b) => if (ord.lt(a, b)) b else a)
}

implicit def toOrdering[A <% Ordered[A]]: Ordering[A] = new Ordering[A] {
    def compare(a: A, b: A): Int = (a < b, b < a) match {
        case (true, _) => -1
        case (_, true) => 1
        case _ => 0
    }
}

println(max(List(1, 2, 3, 2, 1)))

The code runs in both Scala 2.7.7 and 2.8.0 (tested right now in both), though the implicit definition is unnecessary (and possibly harmful in some situations) in Scala 2.8.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top