3
trait JsonOps[J] {
  type ObjectFields
  def partitionObjectFields(fields: ObjectFields, fieldNames: List[String]): (ObjectFields, ObjectFields)
}

def compilerNoLikey[J](stuff: ops.ObjectFields)(implicit ops:JsonOps[J]) = {}

def compilerLikey[J](stuff: Any)(implicit ops:JsonOps[J]) = {
    val stuff2 = stuff.asInstanceOf[ops.ObjectFields]
}

You can see my intent here. I define a type in JsonOps to encapsulate a structure dependant on J. Then later when I want to use this, I have a function that implicitly passes a JsonOps[J] object and also a parameter of type ObjectFields.

Problem is, ObjectFields is defined in ops, which occurs after the stuff in the signature.

How can I unscramble this?

The second def works, but I don't like passing Any around. I'd like the compiler to be able to check what's being passed in.

Brian McCutchon
  • 8,354
  • 3
  • 33
  • 45
Greg
  • 10,696
  • 22
  • 68
  • 98

1 Answers1

4

You should introduce one more type parameter for compilerLikey and write JsonOps with refinement

trait JsonOps[J] {
  type ObjectFields
  def partitionObjectFields(fields: ObjectFields, fieldNames: List[String]): (ObjectFields, ObjectFields)
}

def compilerLikey[J, OF](stuff: OF)(implicit ops: JsonOps[J] { type ObjectFields = OF }) = {}

or using Aux-pattern

trait JsonOps[J] {
  type ObjectFields
  def partitionObjectFields(fields: ObjectFields, fieldNames: List[String]): (ObjectFields, ObjectFields)
}

object JsonOps {
  type Aux[J, OF] = JsonOps[J] { type ObjectFields = OF }
}

def compilerLikey[J, OF](stuff: OF)(implicit ops: JsonOps.Aux[J, OF]) = {}
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66