Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Create TypeRepr of a type with projection #16305

Discussion options

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)
}
You must be logged in to vote

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

Comment options

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.

You must be logged in to vote
3 replies
Comment options

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
}
Comment options

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
Comment options

@KacperFKorban oh I see, I can traverse it recursively. Thanks!

Answer selected by KacperFKorban
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /