2

Could someone please share some insight as to why the following compiles just fine:

import shapeless.Typeable._ import shapeless._ import shapeless.labelled.FieldType import shapeless.record._ import shapeless.tag.@@ trait Typeables[L <: HList] extends DepFn0 { type Out <: HList } object Typeables { type Aux[L <: HList, Out0 <: HList] = Typeables[L] {type Out = Out0} def apply[L <: HList](implicit typeables: Typeables[L]): typeables.type = typeables implicit def hnilTypeables[L <: HNil]: Aux[L, HNil] = new Typeables[L] { type Out = HNil def apply(): Out = HNil } implicit def hlistTypeables[K, V, Rest <: HList] (implicit head: Typeable[V] , tail: Typeables[Rest] ): Aux[FieldType[K, V] :: Rest, Typeable[V] :: tail.Out] = new Typeables[FieldType[K, V] :: Rest] { type Out = Typeable[V] :: tail.Out def apply(): Out = head :: tail() } } object Testy { /** Typeable instance for `T @@ U`. */ implicit def taggedTypeable[T, U] (implicit castT: Typeable[T] , castU: Typeable[U]): Typeable[T @@ U] = new Typeable[T @@ U] { def cast(t: Any): Option[T @@ U] = { if (t == null) None else if (t.isInstanceOf[T]) { val o = t.asInstanceOf[T] Some(tag[U](o)) } else None } def describe = s"${castT.describe} @@ ${castU.describe}" } the[Typeable[Long @@ String]] the[Typeables[Record.`'test -> Long`.T]] // the[Typeables[Record.`'test -> Long @@ String`.T]] } 

whereas commenting in the second last line the[Typeables[Record.`'test -> Long @@ String`.T]] gives a compilation error:

Error:(56, 8) could not find implicit value for parameter t: Typeables[Long with shapeless.tag.Tagged[String] with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("test")],Long with shapeless.tag.Tagged[String]] :: shapeless.HNil] the[Typeables[Record.`'test -> Long @@ String`.T]] Error:(56, 8) not enough arguments for macro method apply: (implicit t: Typeables[Long with shapeless.tag.Tagged[String] with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("test")],Long with shapeless.tag.Tagged[String]] :: shapeless.HNil])Typeables[Long with shapeless.tag.Tagged[String] with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("test")],Long with shapeless.tag.Tagged[String]] :: shapeless.HNil] in object the. Unspecified value parameter t. the[Typeables[Record.`'test -> Long @@ String`.T]]

Using scala 2.12.3, shapeless 2.3.2.

I would have expected it to work with a record with tagged field types since I have provided a correct implicit def for any tagged type, and proved that it works by itself. What am I missing?

1 Answer 1

1

T @@ U is a synonym for T with Tagged[U].

And

Record.`'test -> Long`.T 

is a shorthand for FieldType[Symbol @@ "test", Long] :: HNil.

So

the[Typeables[Record.`'test -> Long @@ String`.T]] 

can be rewritten as

the[Typeables[FieldType[Symbol @@ "test", Long @@ String] :: HNil]] 

(whatever it means) and this one works.

So FieldType[Symbol @@ ..., ...] :: HNil and Record. ... .T are more or less equivalent syntaxes and obviously @@ not always correctly works inside Record. ... .T.

(Here I used Typelevel Scala and scalac flag -Yliteral-types for work with literal types.)

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for shedding light. > "obviously @@ not always correctly works". Is your conclusion that there a bug in the record macro then?
@eirirlar Well, I didn't check the macro. It's just a conclusion from your example. It's also possible that @@ is not expected inside Record. ... .T notation. When you have two alternative syntaxes (for example @@ and Record. ... .T) mixing them sometimes can have weird consequences. Actually I guess I haven't met things like Long @@ String before. I guess I met @@ with Symbol only, in things like Symbol @@ .... Where did you get Long @@ String from? Surely feel free to open a ticket.
For example if you work with strings rather than symbols Record.`"test" -> Long`.T will be just FieldType["test", Long] :: HNil or Long with KeyTag["test", Long] :: HNil.
FieldType[Symbol @@ "test", Long @@ String] :: HNil will be FieldType[Symbol with Tagged["test"], Long with Tagged [String]] :: HNil or Long with Tagged [String] with KeyTag[Symbol with Tagged["test"], Long with Tagged [String]] :: HNil. Isn't it too deeply nested and nested in weird way?
KeyTag and Tagged are two different traits. I thought KeyTag was for Records and Tagged for Symbol literal types. That's why I asked.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.