cats icon indicating copy to clipboard operation
cats copied to clipboard

Implicit resolution fails for newtypes with shapeless `Lazy`

Open ashleymercer opened this issue 5 years ago • 0 comments

Several types in cats such as NonEmptyChain are defined using the newts / newtypes approach: the advantage of this is that there is zero (runtime) overhead to using these types versus the possibly-empty equivalents; however, it leads to several issues, raised here and elsewhere:

  • https://github.com/typelevel/cats/issues/3117
  • https://github.com/typelevel/cats/issues/2928
  • https://github.com/typelevel/cats/issues/2582

To this list I would like to add an issue with implicit resolution when using shapeless Lazy: see https://github.com/milessabin/shapeless/issues/942 for the gory details but, in short, it's impossible to write something like:

def foo(implicit tc: Lazy[Semigroup[NonEmptyChain]]): ...

The non-Lazy version works just fine (as do by-name implicits in scala 2.13+). Interestingly, the Lazy version does work if either (or both) of the following are true:

  • the implementation class (NonEmptyChainImpl in this case) is public
  • the required implicits are explicitly re-imported at the call site (import NonEmptyChain._)

Clearly the end-user can't control the first, and the second is far from ideal (and took several days to discover as a workaround).

It seems like a lot of these issues boil down to variations on https://github.com/scala/bug/issues/6794 and, given that this is unlikely to be fixed in its entirety any time soon, is there some benefit to considering moving away from newtype altogether?

ashleymercer avatar Dec 08 '19 16:12 ashleymercer