scala - 在 Scala 3 中提取元组的子集

标签 scala generics tuples shapeless scala-3

给定一个任意元组,我想提取元组的一个子集。 签名看起来像这样:

def subset[T1 <: Tuple, T2 <: Tuple](t:T1): T2 = ???

其中 T2 是一个元组,其中包含从 T1 中选择的一些成员子集。

使用它看起来像

subset[(String, Int, Boolean), (String, Boolean)]( ("str", 42, true) ) == ("str", true)

我知道这需要广泛使用匹配类型和类型级编程。我觉得使用 Shapeless 非常简单,但我在元组和 HLIST 上缺少标准库中的一些功能。

最佳答案

这看起来像是类型类的工作! (请注意,唯一需要的 Scala 3 特定功能是 *:)

def subset[T1 <: Tuple, T2 <: Tuple](t: T1)(using s: Subset[T1, T2]): T2 = s(t)

opaque type Subset[T1 <: Tuple, T2 <: Tuple] = T1 => T2
object Subset:
  given [T1 <: Tuple]: Subset[T1, EmptyTuple] = _ => EmptyTuple
  given [A, T1 <: Tuple, T2 <: Tuple](using s: Subset[T1, T2]): Subset[A *: T1, A *: T2] =
    case a *: t => a *: s(t)
  given [A, T1 <: Tuple, T2 <: Tuple](using s: Subset[T1, T2]): Subset[A *: T1, T2] =
    case _ *: t => s(t)

See it in Scastie

如果您希望它不管顺序如何工作,它会稍微复杂一些但仍然易于管理:

opaque type Find[T <: Tuple, E] = T => E
object Find:
  given [T <: Tuple]: Find[T, EmptyTuple] = _ => EmptyTuple
  given [A, T <: Tuple]: Find[A *: T, A] = 
    case a *: _ => a
  given [A, H, T <: Tuple](using f: Find[T, A]): Find[H *: T, A] =
    case _ *: t => f(t)

opaque type Subset[T1 <: Tuple, T2 <: Tuple] = T1 => T2
object Subset:
  given [T1 <: Tuple]: Subset[T1, EmptyTuple] = _ => EmptyTuple
  given [A, T1 <: Tuple, T2 <: Tuple](using 
      s: Subset[T1, T2], 
      f: Find[T1, A]
  ): Subset[T1, A *: T2] =
    t => f(t) *: s(t)

def subset[T1 <: Tuple, T2 <: Tuple](t: T1)(using s: Subset[T1, T2]): T2 = s(t)

See it in Scastie

关于scala - 在 Scala 3 中提取元组的子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66444092/

相关文章:

python - 使用 python 从不同长度的元组列表中删除重复项

scala - "parameterized overloaded implicit methods are not visible as view bounds"编译器警告是什么意思?

scala - 未能提交本地 jar 到 spark 集群 : java. nio.file.NoSuchFileException

scala - Scala创建列表[Int]

c# - 参数和带约束的 T 泛型参数有什么区别? C#

c++ - 使用 std::apply 遍历元组元素

scala - Scala 中类参数声明的区别

java - java中的对象扩展

java - 在Java中调用泛型方法: cannot convert Type to generic parameter T

java - 存储 Enum double[] String Triple 的简单设计