Skip to content
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

Interaction between Lazy and tagged types #584

Closed
Astrac opened this issue Apr 26, 2016 · 3 comments · Fixed by #797
Closed

Interaction between Lazy and tagged types #584

Astrac opened this issue Apr 26, 2016 · 3 comments · Fixed by #797
Labels

Comments

@Astrac
Copy link

Astrac commented Apr 26, 2016

There is an interaction between Lazy and tagged types with respect to the automatic derivation of typeclasses; to reproduce it this is a simple example:

sealed trait Readable[T]

object Readable {
  implicit def taggedReadable[A, T, M[_, _]](
    implicit
    r: Lazy[Readable[A]],
    ev: @@[A, T] =:= M[A, T]
  ): Readable[M[A, T]] = ???

  implicit val stringReadable: Readable[String] = ???

  implicit val hnilReadable: Readable[shapeless.HNil] = ???

  implicit def hconsReadable[H, T <: HList](
    implicit
    rh: Lazy[Readable[H]],
    rt: Readable[T]
  ): Readable[H :: T] = ???

  implicit def genericReadable[T, TGen <: HList](
    implicit
    gen: shapeless.Generic.Aux[T, TGen],
    genR: Readable[TGen]
  ): Readable[T] = ???
}

type CustomerTag = W.`'Customer`.T
type CustomerId = String @@ CustomerTag

case class Customer(id: CustomerId, name: String)

implicitly[Readable[CustomerId]]
implicitly[Readable[Customer]]

sealed trait BookTag
type BookId = String @@ BookTag

case class Book(id: BookId, title: String)

implicitly[Readable[BookId]]
implicitly[Readable[Book]]

In this case the derivation fails for both Customer and Book. Interestingly enough removing the Lazy in hconsReadable it compiles; in this case I could just remove it but when the derivation is used in third party libraries that won't compile without Lazy this could be a problem.

@milessabin
Copy link
Owner

The problem appears to be that the tags prevent the Lazy[Readable[H]] being resolved in hconsReadable.

@melrief
Copy link
Contributor

melrief commented Dec 24, 2017

I was playing with this trying to understand what is the issue and I managed to reduce the example to something smaller. I also noticed a pattern depending how you define the implicit Readable for a tagged value. I wrote both methods in this example, commented:

import shapeless._, tag._

object Main {
  sealed trait Readable[A]

  sealed trait IdTag
  type Id = String @@ IdTag

  // Method 1
  //implicit def taggedStringReadable[T]: Readable[String @@ T] = new Readable[String @@ T] { }

  // Method 2
  //implicit def taggedStringReadable[T, M[_, _]](
  //  implicit ev: @@[String, T] =:= M[String, T]): Readable[M[String, T]] = new Readable[M[String, T]] { }

  implicitly[Readable[Id]]         // always compiles
  implicitly[Strict[Readable[Id]]] // doesn't compile with 2
  implicitly[Lazy[Readable[Id]]]   // doesn't compile with 2
}

Method 1 works with Strict/Lazy and without them. Method 2 doesn't work with Strict/Lazy but works without them. The only difference seems to be that 2 needs an implicit parameter. Can that be the problem?
Anyway, I thought this could be useful to debug the problem. I will keep playing with this in the next days. @milessabin if you have an idea in which direction I should go, let me know.

@joroKr21
Copy link
Collaborator

joroKr21 commented Dec 24, 2017

My bet is on calls to dealias in LazyMacros:

  def foo[M[_, _], A, B](mab: M[A, B]) = mab
  def bar(book: Book) = {
    foo(book.id: BookId) // ok
    foo(book.id: String @@ BookTag) // ok
    foo(book.id: String with Tagged[BookTag])
    // [error]  found   : String with shapeless.tag.Tagged[LazyTagged.BookTag]
    // [error]  required: scala.collection.IndexedSeqOptimized[A,B]
    // [error]     foo(book.id: String with Tagged[BookTag])
  }

since Scala can't unify the refinement type A with Tagged[B] with the binary type constructor M[_, _]

joroKr21 added a commit to joroKr21/shapeless that referenced this issue Dec 24, 2017
joroKr21 added a commit to joroKr21/shapeless that referenced this issue Jan 12, 2018
joroKr21 added a commit to joroKr21/shapeless that referenced this issue May 27, 2018
joroKr21 added a commit to joroKr21/shapeless that referenced this issue Oct 13, 2018
joroKr21 added a commit to joroKr21/shapeless that referenced this issue Nov 30, 2019
joroKr21 added a commit to joroKr21/shapeless that referenced this issue Dec 24, 2019
joroKr21 added a commit to joroKr21/shapeless that referenced this issue Apr 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants