This is simply a call to the first class of ToJSON
a "type class" (although it does not look like standardizing these terms, and even your second, more Scala-idiomatic version differs in many important ways, for example, type classes in Haskell).
One of the properties of type classes that I would consider as a definition is that they allow you to restrict common types. Scala provides special syntax to support this in the form of context boundaries, so I can write for example. following:
import io.circe.Encoder def foo[A: Numeric: Encoder](a: A) = ...
This limits type A
both Numeric
and Encoder
instances.
This syntax is not available for the first ToJSON
, and you will have to use something like viewing restrictions (now deprecated) or implicit implicit conversion options.
There are also many kinds of operations that cannot be provided in the first ToJSON
style. For example, suppose we have a Monoid
that uses the standard Scala type class encoding:
trait Monoid[A] { def empty: A def plus(x: A, y: A): A }
And we wanted to translate it into the first style, where we have a non- Monoid
trait that will be the target of implicit conversions from types that we want to consider as monoidal. We were completely unlucky, since we do not have a type parameter that we can refer to our empty
and plus
signatures.
Another argument: the type classes in the standard library ( Ordering
, CanBuildFrom
, etc.) use the second style, like most third-party Scala libraries that you come across.
In short, never use the first version. It will work only when you have only operations with the form A => Whatever
(for a specific concrete Whatever
), does not have pleasant syntactic support and is usually not considered an idiomatic community.