typelevel / typelevel/cats

Implicit resolution fails for newtypes with shapeless `Lazy`

Open
#3,196 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Scala
Stars
5.5k
Forks
1.2k
Avg merge
2d 10h
Merged PRs (30d)
5

Description

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:

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?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the Lazy[Semigroup[NonEmptyChain]] case described in the issue and compare it with the non-Lazy form, using NonEmptyChain and NonEmptyChainImpl as the entry points. Review the linked shapeless and Scala issues before deciding whether a code change is possible; done requires an agreed resolution to the newtype and implicit-resolution design problem.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.