Skip to content

Instantly share code, notes, and snippets.

@Blaisorblade
Created March 27, 2020 16:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Blaisorblade/1835dbfa8b2d015a810f3d0cf24412b8 to your computer and use it in GitHub Desktop.
Save Blaisorblade/1835dbfa8b2d015a810f3d0cf24412b8 to your computer and use it in GitHub Desktop.
Try making `Elem` covariant in `N` — but this fails :-|
import scala.compiletime._
final case class Col[Key, Value](data: Array[Value])
object Frame {
// Covariant version of Tuple.Elem
/** Type of the element a position N in the tuple X */
type Elem[+X <: Tuple, +N <: Int] = X match {
case x *: xs =>
N match {
case 0 => x
case S[n1] => Elem[xs, n1]
}
}
//
extension {
inline def [This <: NonEmptyTuple](t: This).mapply(n: Int): Elem[This, n.type] = {
import scala.runtime.DynamicTuple
DynamicTuple.dynamicApply[This, n.type](t, n).asInstanceOf[Elem[This, n.type]]
}
}
object Types {
type IndexOf[F <: Tuple, Key] <: Int =
F match {
case Col[Key, v] *: cols => 0
case Col[k, v] *: cols => S[IndexOf[cols, Key]]
}
type Get[F <: Tuple, Key] = Elem[F, IndexOf[F, Key]]
}
inline def get[Key, F <: NonEmptyTuple](frame: F) : Types.Get[F, Key] =
frame.mapply(constValue[Types.IndexOf[F, Key]])
}
@Blaisorblade
Copy link
Author

Blaisorblade commented Mar 27, 2020

This works in the presentation compiler, but fails in later phases when checking variance:

[info] Compiling 1 Scala source to /Users/pgiarrusso/git/dotty-staging-experiment/map-fusion/target/scala-0.23/classes ...
[error] -- Error: /Users/pgiarrusso/git/dotty-staging-experiment/map-fusion/src/main/scala/macro.scala:5:25
[error] 5 |  type Elem[X <: Tuple, +N <: Int] = X match {
[error]   |                        ^^^^^^^^^
[error]   |      covariant type parameter N occurs in invariant position in X match {
[error]   |        case
[error]   |          [x, xs <: Tuple] =>>
[error]   |            scala.internal.MatchCase[x *: xs,
[error]   |              N match {
[error]   |                case (0 : Int) => x
[error]   |                case
[error]   |                  [n1 <: Int] =>>
[error]   |                    scala.internal.MatchCase[scala.compiletime.S[n1],
[error]   |                      LazyRef(Frame.Elem[xs, n1])
[error]   |                    ]
[error]   |              }
[error]   |            ]
[error]   |      }
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 1 s, completed Mar 27, 2020 5:56:53 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment