Skip to content
New issue

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

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

Already on GitHub? # to your account

Witness singleton type automatically erased by compile-time type inference #1072

Closed
tribbloid opened this issue Jan 28, 2021 · 3 comments · Fixed by #1240
Closed

Witness singleton type automatically erased by compile-time type inference #1072

tribbloid opened this issue Jan 28, 2021 · 3 comments · Fixed by #1240
Assignees
Labels

Comments

@tribbloid
Copy link

tribbloid commented Jan 28, 2021

This is technically a compiler compatibility issue, so I'm not sure how much work can be done without touching the compiler.

Here is a simple example in scalatest:

class SingletonConstraintSpike extends AnyFunSpec {

  import SingletonConstraintSpike._


  it("3") {

    val v = singletonW.value

//    s3(v) // <----------------------------------------------------------------------------------  breaks!
  }

  it("4") {

    type VT = singletonW.T
    val v: VT = singletonW.value

    s3(v)
  }
}

object SingletonConstraintSpike {

  def s3[T](v: T)(implicit ev: Witness.Aux[T]) = {}

  def adhocW = Witness(3)

  val singletonW = Witness(3)

}

It should be noted that the type of the variable v in case 3 is impeccable (Int(3)), the only problem happens on calling s3 without specifying the correct type parameter Witness._3 (or something equal). The type Int(3) is automatically erased and become Int, for which there is no Witness that can be summoned.

The problem becomes particularly bad when s3 is not just a function with 1 parameter, but part of a type class that has to be recursively called to church-encode an HList-like object. In this case the type class is impossible to be used without declaring their type parameters, which is as bad as writing a chain of type class instances manually.

Can it be solved or we have to wait for the dotty version?

@tribbloid
Copy link
Author

tribbloid commented Jan 28, 2021

BTW, here is an example that may possibly demonstrate 'a type class that has to be recursively called to church-encode an HList-like object':

class SingletonSpike extends AnyFunSpec {

  import shapeless.syntax.singleton._

  object SingletonBroker extends SingletonProductArgs {

    def applyProduct[H <: HList](v: H)(implicit withKeys: ZipWithKeys[H, H]): withKeys.Out = {
    }
  }

  it("should works") {

    val v1 = SingletonBroker("a", 1) // <------------------------------------------------------works
    val v1 = SingletonBroker.applyProduct("a".narrow :: HNil) //<-----------------------breaks!
  }

  it("should not work") {

    val x = 1
//    val v1 = SingletonBroker("a", x)
  }
}

I don't know why calling SingletonBroker.apply directly can work, but here you go. There are too many mysteries that I won't figure out

@tribbloid
Copy link
Author

@joroKr21
Copy link
Collaborator

Fixed by #1242

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants