Scala 3 类型绑定 `<:<` 元组技巧
Posted
技术标签:
【中文标题】Scala 3 类型绑定 `<:<` 元组技巧【英文标题】:Scala 3 type bound `<:<` trick for tuples 【发布时间】:2021-04-18 12:25:18 【问题描述】:在线会议期间,Adam Warski 展示了一个技巧来证明元组具有一定的结构:
第一个实现是
def sequence[T <: Tuple](t: T): Option[InverseMap[T, Option]] =
val unwrapped = t.productIterator.collect case Some(v) => v.toArray[Any]
if unwrapped.length == t.productArity then Some(Tuple.fromArray(unwrapped).asInstanceOf[InverseMap[T, Option]])
else None
允许(但不应该)
sequence(("x", true)) // compiles
还有一个技巧来实现
def betterSequence[T <: Tuple](t: T)(using T <:< Map[InverseMap[T, Option], Option]): Option[InverseMap[T, Option]] =
val unwrapped = t.productIterator.collect case Some(v) => v.toArray[Any]
if unwrapped.length == t.productArity then Some(Tuple.fromArray(unwrapped).asInstanceOf[InverseMap[T, Option]])
else None
betterSequence(("x", true)) // compile error
能不能解释一下
(using T <:< Map[InverseMap[T, Option], Option])
有效,为什么T
是Map
的子类型?
【问题讨论】:
【参考方案1】:InverseMap[T, Foo]
接受一个看起来像(Foo[t1], Foo[t2], ..., Foo[tn])
的元组T
并将其转换为一个元组(t1, t2, ..., tn)
。如果T
没有该结构,即它不是一堆Foo
s,它将无法编译(带有一些神秘的错误)。这是证明元组中只有Option
s 的主要内容。
下一个问题是如何将这种类型插入到betterSequence
方法中。 Map[T, Foo]
将看起来像 (t1, t2, ..., tn)
的元组 T
转换为 (Foo[t1], Foo[t2], ..., Foo[tn])
(InverseMap
的倒数)。因此,Map[InverseMap[T, Option], Option]
只是 T
(想想数学,其中 f(f^-1(x)) 又是 x。绑定的 T <:< T
将始终为真,但前提是 InverseMap
首先成功。
【讨论】:
没错,没有注意到我们有 f(f^-1(x)) 的情况。谢谢!以上是关于Scala 3 类型绑定 `<:<` 元组技巧的主要内容,如果未能解决你的问题,请参考以下文章