Match Types with Structural Types

Would it be possible to add an ability to transform structural types to tuples and tuples to structural types?

trait Vehicle:
  val wheels: Int 
  val range: Int

can be represented as

("wheels",Int,"range",Int ) // wheels - a literal type

Scala 3 gives a very powerfull tool to transform tuples:

type Concat[Xs <: Tuple, +Ys <: Tuple] <: Tuple = Xs match
  case EmptyTuple => Ys
  case x *: xs => x *: Concat[xs, Ys]

Unfortunately the match type cannot help to transform structural types currently.
Such feature will allow to use match types with structural types and it will be very usefull.

1 Like

You could probably write a macro to do that. Shapeless might also have something to help out.

Scala 3 doesn’t have white box macros, how is it possible to write?

transparent inline allows something like whitebox macros. (i.e. transparent inline method can return constant which type will be refined by typer during typing).

1 Like

Is it a real alternative to the match type?

  • Is intellij idea going to support match types in the code assistant?
  • Why do we need match types if transparent inline allows to do the same things?

transparent inline methods do not really provide an ergonomic use for type macro - e.g. you need to cache the result in a variable to extract the type

class TpMacro[Res] {
  type Result = Res

transparent inline def macroType: TpMacro[?] = new TpMacro[("foo", 1, "bar", true)]

val res =  macroType
type Fields = res.Result

val fields: Fields = ("foo", 1, "bar", true)

You don’t need macros to do this in scala 3, I’ve done it entirely with match types, for the only thing I used inline (not macros, mind you), was for row subtype polymorphism.

It works every other compiler version though. Sadly match types + tuple types + inline + singletons have been a whack-a-mole of compiler issues :frowning:. My implementation didn’t compile under 3.0.0, it compiles in 3.0.1 but there are incremental compilation bugs that make it quite useless (you can only use it if the definition is compiled during the same compilation unit as the usage), it compiles and runs correctly under 3.0.2 and 3.1.0-RC1 and it no longer compiles again under 3.1.0-RC2 (crashes the compiler, when you try to use the row row subtype polymorphism)

So eventually it’s going to work well, and it can be done just with match types for the majority of it

In Scala 2 we would have used implicit macros for this. Does this approach not work in Scala 3?

We prototyped a macro that does something quite similar to what you need. See