I would expect that
libraryDependencies += "com.lihaoyi" %% "pprint" % "0.4.1"
case class Entry(id: Int, text: String)
val entry = Entry(1, "hello")
def toPrettyString1[T](o: T) = pprint.tokenize(o).mkString
def toPrettyString2(o: Entry) = pprint.tokenize(o).mkString
println(toPrettyString1(entry)) // I get Entry(1,hello), not what I want
println(toPrettyString2(entry)) // I get Entry(1, "hello"), as expected
The pprint library uses a
PPrint type class to determine how a value of a particular type should be printed. If you have a completely unconstrained type
T, you'll get a
PPrint instance that simply calls
toString on the value, which means you won't get quotation marks or the nice escaping pprint provides.
This is really all pprint can reasonably do if it knows nothing about the type, and even that is arguably too much—many type class-based libraries simply do not provide default instances like this even when there is a possible default interpretation of what the type class operations should do.
toPrettyString2 works as expected because you're calling
tokenize with a value that's statically typed as
PPrint can provide a better instance for. If you want this behavior with a generic type, you'll have to add a context bound:
def toPrettyString3[T: pprint.PPrint](o: T) = pprint.tokenize(o).mkString
scala> println(toPrettyString3(entry)) Entry(1, "hello")
Now you're calling tokenize not with some completely generic
T, but specifically with a
T that you have a
PPrint instance for, and when you call
toPrettyString3 with an
Entry argument, the library will provide a
PPrint instance with the quotation marks, escaping, etc.
T: pprint.PPrint syntax is just sugar for an implicit argument:
def toPrettyString3[T](o: T)(implicit pp: pprint.PPrint[T]) = pprint.tokenize(o)(pp).mkString
You didn't define an implicit
PPrint[Entry] instance, but the library is able to derive reasonable instances for case classes using a macro. You could also define your own instance if for some reason you wanted different behavior, though, and it would override the derived instance.