问题描述
给定一个任意元组,我想提取该元组的一个子集。 签名看起来像:
def subset[T1 <: Tuple,T2 <: Tuple](t:T1): T2 = ???
其中 T2
是一个元组,其中包含从 T1
中选择的一些成员子集。
使用它看起来像
subset[(String,Int,Boolean),(String,Boolean)]( ("str",42,true) ) == ("str",true)
我知道这需要大量使用匹配类型和类型级编程。我觉得 Shapeless 非常简单,但我在元组 vs HLIST 上缺少 std lib 中的一些功能。
解决方法
这看起来像是类型类的工作! (请注意,唯一需要的 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,T2] =
case _ *: t => s(t)
如果您希望它不分顺序地工作,它会稍微复杂一些,但仍然易于管理:
opaque type Find[T <: Tuple,E] = T => E
object Find:
given [T <: Tuple]: Find[T,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](using
s: Subset[T1,T2],f: Find[T1,A]
): Subset[T1,A *: T2] =
t => f(t) *: s(t)
def subset[T1 <: Tuple,T2]): T2 = s(t)