【问题标题】:Extract a subset of a tuple in Scala 3在 Scala 3 中提取元组的子集
【发布时间】:2021-06-01 06:34:37
【问题描述】:

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

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

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

使用它看起来像

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

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

【问题讨论】:

  • 可能值得使用 Shapeless 添加您的解决方案,以便有人可以使用 Scala 3 版本进行并行处理。
  • subset[(String, String, String), (String, String)](("foo", "bar", "baz")) 会是什么? ("foo", "bar")?
  • 同一类型出现多次时不必编译。我基本上不在乎那个案子。
  • 我猜这就像一个过滤器,谓词检查 T2 中是否存在每个元素类型
  • 能否在您的问题中添加subset 应该如何处理subset[(Int, String), (String, Int)] 和其他边缘情况?

标签: scala generics tuples shapeless scala-3


【解决方案1】:

这看起来像是类型类的工作! (请注意,唯一需要的 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

【讨论】:

  • 如果它们的顺序不同,这就会分崩离析,对吧?
  • @Felix 哦,你想让它不分顺序地编译吗?给我一些时间来解决这个问题,然后
  • @Felix 让我知道这是否适合您。
  • 这令人印象深刻——我必须仔细阅读它,但我认为这解决了我的问题!
猜你喜欢
  • 2022-01-21
  • 2015-10-08
  • 2018-04-06
  • 1970-01-01
  • 2018-08-27
  • 2021-03-26
  • 1970-01-01
  • 2021-02-05
相关资源
最近更新 更多