-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Create TypeRepr of a type with projection #16305
-
What is the right way to build up a TypeRepr
with projection?
More specifically, I'm trying to find a way to build TypeRef(repr, λ)
.
Short version:
// given trait ServiceK[U[_[_]]] // ServiceK is just to demo the usage, the culprit is IdK[A]#λ type IdK[A] = { type λ[F[_]] = F[A] }
It's possible to create the following TypeRepr
: TypeRepr.of[ServiceK[IdK[Int]#λ]]
What is the right way to build up IdK[Int]#λ
manually? I'm looking for smth like:
// this is a non working pseudocode TypeRef( TypeRepr.of[IdK].appliedTo(TypeRepr.of[Int]), λ // <--- this one )
A Longer version:
// given trait ServiceK[U[_[_]]] type IdK[A] = { type λ[F[_]] = F[A] } // macro function itself def idK(using Quotes): Expr[Boolean] = { import quotes.reflect.* // There is a need to construct the following TypeRepr via primitives // The problem is in IdK[Int]#λ but when written this way it's easier to get what I'm trying to do // also the println(expected) is much nicer val expected = TypeRepr.of[ServiceK[IdK[Int]#λ]] // expected println // AppliedType( // TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class com)),object test),ServiceK), // List( // TypeRef( // AppliedType( // TypeRef(ThisType(TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class com)),object test),Test$)),IdK),List(TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class <root>)),object scala),Int))), // λ // ) // ) // ) // I could not find a way to build the IdK[Int]#λ projection here val actual = TypeRepr.of[ServiceK].appliedTo(TypeRepr.of[IdK].appliedTo(TypeRepr.of[Int])) // this is a non working pseudocode // val actual = TypeRepr.of[ServiceK].appliedTo( // TypeRef(TypeRepr.of[IdK].appliedTo(TypeRepr.of[Int]), λ) // ) Expr(actual =:= expected) }
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 5
A way to build it manually would be to do something like this:
import scala.quoted.* trait ServiceK[U[_[_]]] type IdK[A] = { type λ[F[_]] = F[A] } inline def idK: Boolean = ${ idKImpl } def idKImpl(using Quotes): Expr[Boolean] = { import quotes.reflect.* val expected = TypeRepr.of[ServiceK[IdK[Int]#λ]] // IdK[Int] is encoded as // java.lang.Object { // type λ >: [F >: scala.Nothing <: [_3ドル >: scala.Nothing <: scala.Any] => scala.Any] => F[scala.Int] <: [F >: scala.Nothing <: [_3ドル >: scala.Nothing <: scala.Any] => scala.Any] => F[scala.Int] // } // i.e. a Refinement type (Object + the type declaration) TypeRepr.of[IdK].appliedTo(TypeRepr.of[Int]) match { case repr
Replies: 1 comment 3 replies
-
A way to build it manually would be to do something like this:
import scala.quoted.* trait ServiceK[U[_[_]]] type IdK[A] = { type λ[F[_]] = F[A] } inline def idK: Boolean = ${ idKImpl } def idKImpl(using Quotes): Expr[Boolean] = { import quotes.reflect.* val expected = TypeRepr.of[ServiceK[IdK[Int]#λ]] // IdK[Int] is encoded as // java.lang.Object { // type λ >: [F >: scala.Nothing <: [_3ドル >: scala.Nothing <: scala.Any] => scala.Any] => F[scala.Int] <: [F >: scala.Nothing <: [_3ドル >: scala.Nothing <: scala.Any] => scala.Any] => F[scala.Int] // } // i.e. a Refinement type (Object + the type declaration) TypeRepr.of[IdK].appliedTo(TypeRepr.of[Int]) match { case repr: Refinement => val actual = TypeRepr.of[ServiceK].appliedTo(repr.info) Expr(actual =:= expected) } }
Though I am not sure if that will be the intended way.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 2 -
🎉 1
-
Hey @KacperFKorban thanks! It works for me and in this particular case, awesome.
Just a lil bit of extra: is it possible to pick up one projection here in case IdK
has more than one?
type IdK[A] = { type λ[F[_]] = F[A] type T = Int }
Beta Was this translation helpful? Give feedback.
All reactions
-
In that case, the TypeRepr
will be a Refinement
with a parent that is also a Refinement
, so you will have to go up the parent hierarchy until you find the Refinement
with the correct name
.
In this specific case (a hardcoded version) will look something like this:
val actual = TypeRepr.of[ServiceK].appliedTo(repr.parent.asInstanceOf[Refinement].info) // Not sure if the order will always be the same as in source, but the idea stays the same
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1
-
@KacperFKorban oh I see, I can traverse it recursively. Thanks!
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1