title: Problems generalizing Scala type classes
body: <p>While working on a Scala project that used the Type Class pattern, I ran into what appears to be a serious problem in how the language implements the pattern: Since Scala type-class implementations must be managed by the programmer and not the language, any variable belonging to a type-class can never become annotated as a parent type unless its type-class implementation is taken with it.</p>
  
  <p>To illustrate this point, I've coded up a quick example program. Imagine you were trying to write a program that could handle different kinds of employees for a company and could print reports on their progress. To solve this with the type-class pattern in Scala, you might try something like this:</p>
  
  <pre><code>abstract class Employee
  class Packer(boxesPacked: Int, cratesPacked: Int) extends Employee
  class Shipper(trucksShipped: Int) extends Employee
  </code></pre>
  
  <p>A class hierarchy modelling different kinds of employees, simple enough. Now we implement the ReportMaker type-class.</p>
  
  <pre><code>trait ReportMaker[T] {
      def printReport(t: T): Unit
  }
  
  implicit object PackerReportMaker extends ReportMaker[Packer] {
      def printReport(p: Packer) { println(p.boxesPacked + p.cratesPacked) }
  }
  
  implicit object ShipperReportMaker extends ReportMaker[Shipper] {
      def printReport(s: Shipper) { println(s.trucksShipped) }
  }
  </code></pre>
  
  <p>That's all well and good, and we can now write some kind of Roster class that might look like this:</p>
  
  <pre><code>class Roster {
      private var employees: List[Employee] = List()
  
      def reportAndAdd[T &lt;: Employee](e: T)(implicit rm: ReportMaker[T]) {
         rm.printReport(e)
         employees = employees :+ e
      }
  }
  </code></pre>
  
  <p>So this works. Now, thanks to our type-class, we can pass either a packer or a shipper object into the reportAndAdd method, and it will print the report and add the employee to the roster. However, writing a method that would attempt to print out the report of every employee in the roster would be impossible, without explicitly storing the rm object that gets passed to reportAndAdd!</p>
  
  <p>Two other languages that support the pattern, Haskell and Clojure, don't share this problem, since they deal with this problem. Haskell's stores the mapping from datatype to implementation globally, so it is always 'with' the variable, and Clojure basically does the same thing. Here's a quick example that works perfectly in Clojure.</p>
  
  <pre><code>    (defprotocol Reporter
        (report [this] "Produce a string report of the object."))
  
      (defrecord Packer [boxes-packed crates-packed]
        Reporter
        (report [this] (str (+ (:boxes-packed this) (:crates-packed this)))))
      (defrecord Shipper [trucks-shipped]
        Reporter
        (report [this] (str (:trucks-shipped this))))
  
      (defn report-roster [roster]
        (dorun (map #(println (report %)) roster)))
  
      (def steve (Packer. 10 5))
      (def billy (Shipper. 5))
  
      (def roster [steve billy])
  
      (report-roster roster)
  </code></pre>
  
  <p>Apart from the rather nasty solution of turning the employee list into type List[(Employee, ReportMaker[Employee]), does Scala offer any way to solve this issue? And if not, since the Scala libraries make extensive use of Type-Classes, why hasn't it been addressed?</p>