Skip to content

Instantly share code, notes, and snippets.

@bishabosha
Last active May 6, 2025 16:25
Show Gist options
  • Save bishabosha/ee9e1968389a398230291b94def4ad48 to your computer and use it in GitHub Desktop.
Save bishabosha/ee9e1968389a398230291b94def4ad48 to your computer and use it in GitHub Desktop.
Named Tuple copy method
import NamedTuple.{Names, AnyNamedTuple, NamedTuple}
type ContainsAll[X <: Tuple, Y <: Tuple] <: Boolean = X match
case x *: xs => Tuple.Contains[Y, x] match
case true => ContainsAll[xs, Y]
case false => false
case EmptyTuple => true
type FilterName0[N, Ns1 <: Tuple, Vs1 <: Tuple] <: Option[Any] =
(Ns1, Vs1) match
case (N *: ns, v *: vs) => Some[v]
case (_ *: ns, _ *: vs) => FilterName0[N, ns, vs]
case (EmptyTuple, EmptyTuple) => None.type
type Copy0[N <: Tuple, N1 <: Tuple, V1 <: Tuple, N2 <: Tuple, V2 <: Tuple, Acc <: Tuple] <: AnyNamedTuple = (N1, V1) match
case (n1 *: ns1, v1 *: vs1) => FilterName0[n1, N2, V2] match
case Some[v2] => Copy0[N, ns1, vs1, N2, V2, v2 *: Acc]
case _ => Copy0[N, ns1, vs1, N2, V2, v1 *: Acc]
case (EmptyTuple, EmptyTuple) => NamedTuple[N, Tuple.Reverse[Acc]]
type Copy[T <: AnyNamedTuple, U <: AnyNamedTuple] <: AnyNamedTuple = (T, U) match
case (NamedTuple[ns1, vs1], NamedTuple[ns2, vs2]) => Copy0[ns1, ns1, vs1, ns2, vs2, EmptyTuple]
extension [N <: Tuple, V <: Tuple](t: NamedTuple[N, V]) def copy[N1 <: Tuple, V1 <: Tuple](u: NamedTuple[N1,V1])(using ContainsAll[N1, N] =:= true): Copy[NamedTuple[N, V], NamedTuple[N1,V1]] = ???
lazy val foo = (x = 23, y = 41).copy((y = "abc"))
lazy val err = (x = 23, y = 41).copy((z = "abc")) // error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment