milessabin / shapeless

Generic programming for Scala

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Poly function cannot resolve implicit, works with explicit invocation

elefthei opened this issue · comments

I would like to call polyToString recursively and polymorphically instead of manually specifying the caseManager implicit to use. Since it works in all other members, it is strange that the Poly does not resolve the implicit in this case. Look at the XXX comment.

// A sealed trait (sum) and some case classes (products)
sealed trait Entity
case class Employee(name : String, uid: Int) extends Entity
case class Manager(name: String) extends Entity
case class Department(name: String, manager : Manager, employees: List[Employee]) extends Entity

// Test case
object Data {
  val a: Employee = new Employee("a", 100)
  val b: Employee = new Employee("b", 101)
  val c: Employee = new Employee("c", 102)
  val john: Manager = new Manager(name = "John Boss")
  val sales: Department = new Department("Sales", manager = john, employees = List(a, b, c))
}

// Enter Polymorphic functions
object polyToString extends Poly1 {

  // utility, indent a string
  private def indent(n : Int, s: String) : String = " ".repeat(n) + s

  implicit def caseEmployee = use((e : Employee) => s"EmployeeID: ${e.uid} * Name: ${e.name}")
  implicit def caseListEmployees = use ((le: List[Employee]) =>
    le.map(polyToString).map(indent(4, _)).mkString("\n"))
  implicit def caseManager = use((m : Manager) => s"Manager-In-Chief: ${m.name}")
  
  implicit def caseDepartment = use((d: Department) =>
    s"Glorious department of ${d.name}\n"
      + indent(2, polyToString(d.manager : Manager)) + "\n" //XXX: This works if I call caseManager directly, looks like a call to `polyToString` cannot resolve the implicit for Manager
      + polyToString(d.employees))

  implicit def caseDefault[A] = use((a: A) => {
    println(s"Warning: Using default function for ${a.toString}")
    a.toString
  })
}

object Main extends App {
  import Data._
  println(polyToString(sales))
}

The example is a little bit dense for me to be able to say at a glance, but I think this is most likely an implicit ambiguity/priority issue. I suggest you take it to the shapeless gitter channel and ask for advice there.

If you establish that there is a bug in shapeless, please reopen this issue.