Skip to content

Can't define typeclasses for union and intersection types #12246

@japgolly

Description

@japgolly

Compiler version

3.0.0-RC3

Minimized code

case class F[A]()

given F[Int] = F()
given F[Boolean] = F()

given [A, B](using F[A], F[B]): F[A | B] = F()
given [A, B](using F[A], F[B]): F[A & B] = F()

object Test:

  summon[F[Int | Int]]     // ok
  summon[F[Int | Boolean]] // error

  summon[F[Int & Int]]     // ok
  summon[F[Int & Boolean]] // error

Output

[error] -- Error: src/main/scala/a.scala:12:26 ---------------
[error] 12 |  summon[F[Int | Boolean]] // error
[error]    |                          ^
[error]    |ambiguous implicit arguments of type F[Int | Boolean] found for parameter x of method summon in object Predef.
[error]    |I found:
[error]    |
[error]    |    given_F_|[A, B](
[error]    |      /* ambiguous: both given instance given_F_Int and given instance given_F_Boolean match type F[A] */
[error]    |        summon[F[A]]
[error]    |    , 
[error]    |      /* ambiguous: both given instance given_F_Int and given instance given_F_Boolean match type F[B] */
[error]    |        summon[F[B]]
[error]    |    )
[error]    |
[error]    |But both given instance given_F_Int and given instance given_F_Boolean match type F[A].
[error] -- Error: src/main/scala/a.scala:15:26 ---------------
[error] 15 |  summon[F[Int & Boolean]] // error
[error]    |                          ^
[error]    |ambiguous implicit arguments of type F[Int & Boolean] found for parameter x of method summon in object Predef.
[error]    |I found:
[error]    |
[error]    |    given_F_&[A, B](
[error]    |      /* ambiguous: both given instance given_F_Int and given instance given_F_Boolean match type F[A] */
[error]    |        summon[F[A]]
[error]    |    , 
[error]    |      /* ambiguous: both given instance given_F_Int and given instance given_F_Boolean match type F[B] */
[error]    |        summon[F[B]]
[error]    |    )
[error]    |
[error]    |But both given instance given_F_Int and given instance given_F_Boolean match type F[A].
[error] two errors found

Expectation

It should compile. We need a way to generically define typeclasses for unions and intersection types.

I think what's happening is that, because union and intersection types are commutative, the implicit search correctly identifies that A | B can be reversed to B | A in order to satisfy its search. In this case at least, it doesn't matter which is chosen - they're identical so implicit search should just choose A | B.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions