Skip to content

Ergonomics of opaque types and delegates #6716

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
milessabin opened this issue Jun 20, 2019 · 5 comments
Closed

Ergonomics of opaque types and delegates #6716

milessabin opened this issue Jun 20, 2019 · 5 comments
Assignees

Comments

@milessabin
Copy link
Contributor

An opaque type and its underlying type have exactly the same representation, so it should be possible to opt to directly reuse delegates for the underlying as delegates for the opaque type. This is pretty much the gist of Andres Loh's Deriving Via paper.

Ideally we'd be able to write something like,

trait Monad[T]
class Foo
object Foo {
  delegate for Monad[Foo]
}

opaque type Bar = Foo
object Bar {
  delegate for Monad[Bar] = the[Monad[Foo]]
}

object Test {
  val mf = the[Monad[Foo]]
  val mb = the[Monad[Bar]]
}

But this doesn't work currently, at least in part because recent changes to opaque types mean they no longer have an implicit scope of their own. The closest I think we can get right now is something like,

trait Monad[T]
class Foo
object Foo {
  delegate for Monad[Foo]
}

opaque type Bar = Foo
delegate for Monad[Bar] = the[Monad[Foo]].asInstanceOf

object Test {
  val mf = the[Monad[Foo]]
  val mb = the[Monad[Bar]]
}

which has an ugly (and surely unnecessary?) cast and an untidy top-level delegate definition.

Can we do any better?

@SystemFw
Copy link

SystemFw commented Jun 20, 2019

Again, super quick comment (sorry for butting in without a lot of context, just had a quick discussion with Miles).
It seems a bit counterintuitive that opaque types won't have a companion object and therefore a convenient implicit scope of their own, given that one of the primary ways to add semantics to them is via typeclass instances.

@abgruszecki
Copy link
Contributor

Since the surrounding object still forms an implicit scope, is there any problem with moving the type inside the object?

trait Monad[T]
class Foo
object Foo {
  delegate for Monad[Foo]
}

object Bar {
  opaque type Bar = Foo
  delegate for Monad[Bar] = the[Monad[Foo]]
}

object Test {
  import Bar.Bar
  val mf = the[Monad[Foo]]
  val mb = the[Monad[Bar]]
}

@odersky
Copy link
Contributor

odersky commented Jun 24, 2019

We agreed that we should bring companion objects for opaque types back, as far as implicit scope is concerned.

@SystemFw
Copy link

nice :)

@dwijnand
Copy link
Member

@AleksanderBG seeing as type aliases can be top level, you can type alias the opaque alias and avoid the import... :-P

Or actually, you can export it (possibly pending #6729 ?).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants