Skip to content

Instantly share code, notes, and snippets.

@bishabosha
Created March 18, 2025 19:56
Show Gist options
  • Save bishabosha/940155a8e9306a1d6495efe3b44b4755 to your computer and use it in GitHub Desktop.
Save bishabosha/940155a8e9306a1d6495efe3b44b4755 to your computer and use it in GitHub Desktop.
Type function DSL scala
// example of a "type level function" resolved via implicit search using inline match - to get around named tuple types not working with match types
sealed trait Foo
type TypeFun[Cases <: Tuple] = [T] =>> TypeFun.Resolved[T, Cases]
type ->>[Case, R] = (Case, R)
object TypeFun:
sealed trait Wild[F[_]]
final class Resolved[T, Cases <: Tuple]:
type Out
object Resolved:
type Aux[T, Cases <: Tuple, R] = Resolved[T, Cases] { type Out = R }
transparent inline given resolved[T, Cases <: Tuple]: Resolved[T, Cases] =
resolveCases[T, Cases, Cases]
transparent inline def resolveCases[T, Cases <: Tuple, C <: Tuple]: Resolved[T, Cases] =
inline compiletime.erasedValue[C] match
case _: ((T, r) *: _) => Resolved[T, Cases].asInstanceOf[Resolved.Aux[T, Cases, r]]
case _: (Wild[f] *: _) => Resolved[T, Cases].asInstanceOf[Resolved.Aux[T, Cases, f[T]]]
case _: (_ *: rest) => resolveCases[T, Cases, rest]
type Bar = TypeFun[(Foo ->> (a: Int, b: Int), TypeFun.Wild[[T] =>> NamedTuple.From[T]])]
val x0 = summon[Bar[Foo]]
val x0Check: x0.Out = (a = 1, b = 2)
val y0 = summon[Bar[(1, 2)]]
val y0Check: y0.Out = (1, 2)
val z0 = summon[Bar[(a: Int, b: Int)]]
val z0Check: z0.Out = (a = 1, b = 2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment