-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Recursive given not working #18267
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
Comments
More aggressive minimization: object LabelledList:
trait Enc[Tup <: Tuple]:
def enc(tup: Tup): Unit
given e: Enc[EmptyTuple] with
def enc(emptyTuple: EmptyTuple) = ()
given ne[N <: Singleton & String, V, T <: Tuple: Enc]: Enc[(N, V) *: T] with
def enc(tuple: (N, V) *: T): Unit = ()
object BugTests:
def main() =
val works = LabelledList.ne.enc(
("col1" -> 1) *: EmptyTuple
)
val fails = LabelledList.ne.enc(
("col1" -> 1) *: ("col2" -> 2) *: EmptyTuple
)
|
This isn't a bug. You can't call |
Thank you @dwijnand for your time answering this. Can you explain me why it works for |
It works for empty, because you're using LabelledList.e, which takes an EmptyTuple. It works for 1-tuple, because you're taking |
Hi, @dwijnand, thank you for the explanation. I tried a different approach using extension methods and it still didn't work (not even the trait Enc1[Tup <: Tuple]:
extension (tup: Tup) def enc: FromTuple[Tup]
given e: Enc1[EmptyTuple] with
extension (tup: EmptyTuple) def enc = Empty
given ne[N <: Singleton & String, V, T <: Tuple: Enc1]: Enc1[(N, V) *: T] with
extension (tuple: (N, V) *: T) def enc =
val (n, v) *: t = tuple
Cons(Labelled(n, v), t.enc) val obtained = (
("col2" -> 2) *: EmptyTuple
).enc
In this case, wouldn't the types be available for constructing |
I don't understand why the complication. Why not strip it back to something like this, that works: opaque type Labelled[Name <: String, Value] = Value
object Labelled:
def apply[Name <: String, Value](name: Name, value: Value): Labelled[Name, Value] = value
sealed abstract class LabelledList
object LabelledList:
final case class Cons[
Name <: String,
Value,
Tail <: LabelledList
](
col: Labelled[Name, Value],
tail: Tail
) extends LabelledList
case object Empty extends LabelledList
type FromTuple[Tup <: Tuple] <: LabelledList = Tup match {
case (n, v) *: t => Cons[n, v, FromTuple[t]]
case _ => Empty.type
}
trait Enc[Tup <: Tuple]:
def enc(tup: Tup): FromTuple[Tup]
given e: Enc[EmptyTuple] with
def enc(emptyTuple: EmptyTuple) = Empty
given ne[N <: String, V, T <: Tuple: Enc]: Enc[(N, V) *: T] with
def enc(tuple: (N, V) *: T) =
val (n, v) *: t = tuple
Cons(Labelled(n, v), summon[Enc[T]].enc(t))
def enc[Tup <: Tuple](tup: Tup)(using enc: Enc[Tup]): FromTuple[Tup] = enc.enc(tup)
class BugTests:
val t0 = LabelledList.enc(EmptyTuple)
val t1 = LabelledList.enc(("col2" -> 2) *: EmptyTuple)
val t2 = LabelledList.enc(("col1" -> 1) *: ("col2" -> 2) *: EmptyTuple) |
Hi @dwijnand, thank you again for your time. It indeed worked without the Unfortunately with your suggestion this would compile, defeating the purpose of val obtained = LabelledList.enc(
("col1" -> 1) *: ("col2" -> 2) *: EmptyTuple
)
val expected = LabelledList.Cons(
Labelled("col1", 1),
LabelledList.Cons(
Labelled("cols00000000000000000000000002", 2),
LabelledList.Empty
)
)
assertEquals(obtained, expected) |
Compiler version
3.3.0
Minimized code
I tried my best to minimize the code without losing the "essence" of the problem:
Output
Expectation
Both tests
empty
and1-tuple
work, but2-tuple
doesn't. I would expect it to just work recursively.Maybe similar to #18211, but I couldn't say for sure.
The text was updated successfully, but these errors were encountered: